Vulkan- 性能及精细化
Vulkan 是新一代的图形显示 API。也有业界称之为“下一代的 OpenGL”,不言而喻人们也总喜欢拿 Vulkan 和 OpenGL(已经经历了 20 年之久的非常成熟的当代图形 API 的大成者)作对比以突出其在某些场景下的优势。
Vulkan--API 设计哲学
Explicit(明确、透明):GPU Driver 做更少的事情,把更多的控制权交给开发
Streamlined(精简):更快的性能,更低的开销,更少的延
Portable(可移植):Cloud, desktop, console, mobile and embedde
Extensible (可扩展):支持新功能的扩展,推动行业技术进
再用一句话概括下,Vulkan 是下一代高性能及精细化控制的开放的跨平台的图形 API。下面我们也会围绕这句总结展开来说。
开放
Vulkan 是由 Khronos Group 组织发布的跨平台图像渲染引擎,该组织还发布了诸如 OpenGL、OpenGL ES、WebGL 等图形 API。Vulkan 脱胎于 Mantle,其包含部分 Mantle 组件;Mantle 是面向 3D 游戏的新一代图形渲染 API, 可以让开发人员直接操作 GPU 的底层硬件,从而提高硬件利用率和游戏性能。但遗憾的是因为 AMD 行业影响力不足, Mantle 并没有成为全行业的标准。
然而微软参考 AMD Mantle 的思路开发了 DirectX 12, 苹果则提出了 Metal。2015 年 Khronos 从 AMD 接过 Mantle 并孵化出后来的 Vulkan,并推动 Vulkan 的大力发展。Vulkan 的开发者来自图形领域的各行各业,有 GPU 厂商,有系统厂商,有游戏引擎厂商
跨平台
Vulkan 的开发者来自图形领域的各行各业,有 GPU 厂商,有系统厂商,有游戏引擎厂,所以与生俱来的属性就是跨平台,以全行业的统一标准为终极目标。其支持桌面、移动设备、游戏主机、嵌入式等等。
精细化控制
传统的图形 API,驱动是个大包大揽的角色,驱动程序会跟踪对象状态,会帮你做 API 验证,内存管理,线程管理等大部分工作。驱动帮开发者隐藏了很多底层细节,当然这样对开发者来说是个福音,因为以开发者的视角看这样操作起来简单,不需要考虑太多底层的实现及错误处理。驱动甚至在 api 调用出错的时候都能帮助处理,保证应用正常运行。但是为了实现这些,驱动会浪费更多的性能,应用程序经过调试并且正确运行时,会消耗宝贵的 CPU 性能,在一些复杂场景和极致的性能体验场景下,这种问题会指数倍的放大而且开发者会很沮丧,因为他们能缓解这种局面的能力并不多,有时候也会非常复杂,因为驱动在不同平台和厂商下实现是不一样的。
Vulkan 为了解决这个问题,提供了更显示的 API,更精细化的 GPU 底层控制逻辑,并将驱动视为一个应用和 GPU 之间的桥梁,帮忙做数据通信及指令传递。Vulkan 将状态跟踪、同步和内存管理交给了应用程序开发人员,甚至不包括执行期的错误检查层。一旦 API 使用出错,应用就会出现 crash。没人帮应用兜底,所有事情都交由应用打理。驱动层干的事情少了,隐藏的 bug 也就少了。
Vulkan 让程序有更多的权限和责任自主的处理调度和优化,而不依赖于驱动尝试在后台的优化。但对于开发者其使用的复杂度也就变高了,并且在一定程度上稳定性降了。
虽然这种方式无疑增加了 API 使用的复杂度和困难度,但换来的是性能上巨大的提升。单单是在驱动中去掉 API 验证,就把性能提升了 9 倍。
性能
多线程
Vulkan 基于 Queue 的 API 设计对多线程非常友好,同时也提供了多种 Synchronization 的方法。常见的并行方法有两种,第一种是在 CPU 端并行的更新 Buffer 中的数据。这里要注意的是,多线程的情况下更新资源要保证安全。第二种是并行的方式带来的性能提升更加显著,尤其是在渲染非常复杂的场景。
第一种如果你的程序渲染的非常高效,同时在 CPU 端需要处理好几帧的数据,所以程序可以用 Round Robin 的方法更新并且使用这些资源。这个时候要保证安全更新资源。Vulkan 的 Event 可以被插入在 Command Buffer 中,在使用指定资源的调用后面可以更高效的保正资源的安全性。
第二种并行的方式带来的性能提升更加显著,尤其是在渲染非常复杂的场景下,这也是 Vulkan 相比传统 API 提升最显著的地方,那就是并行的在不同线程上生成场景不同部分的渲染任务,并且生成自己的 Command Buffer,不用任何线程间的 Synchronization。最后,不同的线程可以将 Command Buffer 的 Handle 传给主线程然后由主线程将它们写入 Queue 中,也可以直接写入子线程中的 per-thread Queue 递交给 GPU。给开发者提供了充分发挥 CPU 多核多线程的优势。在复杂场景下,性能的提升非常可观!
不过 Queue 的任务递交时间并不是完全可以忽略的,所以这里还是建议将 Command 传给主线程一起递交。这样的模式达到了计算资源利用的最大化,多个 CPU 核都参与了场景的渲染,并且有大量的渲染任务同时递交给 GPU 最大化了 GPU 的吞吐量。
预编译 shader
驱动层不提供前端 shader 编译器。仅仅支持标准可移植中间表示二进制代码(SPIR-V),可支持 AOT 和运行时。既提高了执行 Shaders 的效率又添加了将来着色语言的灵活性。Vulkan 也可以使用离线的 shader
移动平台的支持进展
Android 7.0 添加了对 Vulkan 的支持, Q 开始将使用 vulkan 进行默认的 UI 渲染。
Flutter 框架的底层图形库 Skia 是支持 Vulcan 的,Fuchsia 谷歌的新一代跨平台系统也支持。
版权声明: 本文为 InfoQ 作者【江湖修行】的原创文章。
原文链接:【http://xie.infoq.cn/article/3f2888c6013ffc109892ff6ac】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论