什么是 Vulkan?
Vulkan 是由 Khronos Group 开发的跨平台图形 API(应用程序编程接口)。Vulkan API 是一个标准,因此可以在多种设备、平台和各种不同的编程语言中实现。
Vulkan 被设计用于高性能多线程应用程序。Vulkan 尤其受益于其设计,因为它更加明确,减少了图形驱动程序执行的猜测。正确使用 Vulkan 可以产生高水平的性能、低延迟和一致的帧时间。
Vulkan API 概述
Vulkan API 提供了一个函数列表、要传入的参数以及返回类型。该 API 以 C 编程语言编写,应与绝大多数语言兼容。
尽管本教程是用 C++ 编写的,但将其移植到其他低级语言(如 Rust 甚至纯 C)应该很简单。
何时使用 Vulkan
如果您的主要瓶颈在 GPU 端,那么实施 Vulkan 不太可能充分提高性能,使其值得付出努力。应该提到的是,与 OpenGL 相比,Vulkan 明显更难使用,并且其额外的复杂性通常意味着更长的开发时间。
如果您的应用程序包含大型地图、动态世界或具有大量对象的 CAD 类型场景,那么 Vulkan 的多线程功能可能会提高性能。
移动市场存在碎片化问题。并非每部手机都实现了 Vulkan(尤其是旧手机),而且在实现了 Vulkan 的手机中,您可能会遇到驱动程序质量问题。具有良好 Vulkan 驱动程序的手机尤其受益于较低的 CPU 开销,并且通常会看到广泛的性能提升,同时使用更少的电池。
跨平台
Vulkan 的设计与其他图形 API 相比是独特的,因为它为移动设备和桌面设备提供了相同的 API。这意味着 Vulkan 中的许多功能是可选的,使用它们需要显式地开启它们。在移动设备上不支持但在大多数桌面 GPU 上支持的功能是很常见的。
在桌面和移动设备上运行 Vulkan 驱动的应用程序时,您可以选择使用一个或两个核心渲染路径。建议运行两个核心渲染路径,因为另一种选择将以牺牲次优性能为代价。API 的统一意味着这两个渲染路径可以共享代码。
本教程将重点介绍为桌面编写 Vulkan,但是我们将介绍两种类型的 GPU 之间的许多差异。
验证层
Vulkan API 非常庞大,因此很容易犯错误,但这就是验证层发挥作用的地方。
验证层是 Vulkan 中的一个可选功能,用于检测和报告 API 的不正确使用。
验证层的工作原理是拦截您的函数调用并对数据执行验证。如果所有数据都正确验证,则将执行对驱动程序的调用。应该注意的是,拦截函数和运行验证会带来性能损失。
验证层对于捕获错误很有用,例如使用不正确的配置、使用错误的枚举、同步问题和对象生命周期。建议在开发时启用验证层,以确保您的代码符合规范要求。在没有任何报告的验证错误的情况下运行您的应用程序是一个好兆头,但这不应用作衡量您的应用程序在不同硬件上运行状况的指标。我们建议在尽可能多的不同设备上测试您的应用程序。
重要的是要注意,验证层不会捕获诸如未初始化的内存和错误的指针之类的错误。强烈建议使用 Address Sanitizer 和 Valgrind 等工具。请注意,图形驱动程序在使用这些工具时经常会产生误报,使其输出非常嘈杂。
用法和一般思维模式
在 Vulkan API 中,几乎所有内容都是围绕您手动创建然后使用的对象设计的。这不仅适用于实际的 GPU 资源,如图像/纹理和缓冲区(用于内存或顶点数据之类的内容),还适用于许多“内部”配置结构。
例如,像光栅化模式这样的 GPU 固定功能存储到一个 Pipeline 对象中,该对象保存着色器和其他配置。在 Opengl 和 DX11 中,这是在渲染时“动态”计算的。当您使用 Vulkan 时,您需要考虑是否值得缓存这些对象,或者在渲染时动态创建它们。像 Pipeline 这样的一些对象创建成本很高,因此最好在加载屏幕或后台线程中创建它们。其他对象创建成本较低,例如 DescriptorSet,并且在渲染期间需要它们时创建它们是可以的。
由于 Vulkan 中的一切默认情况下都是“预先构建”的,这意味着 GPU 中的大多数状态验证将在您创建对象时完成,并且渲染本身执行的工作较少且速度更快。很好地理解这些对象是如何创建和使用的,将使您能够控制一切的执行方式,从而使帧率平稳。
当执行实际的 GPU 命令时,GPU 上的所有工作都必须记录到 CommandBuffer 中,并提交到 Queue 中。您首先分配一个命令缓冲区,开始在其中编码内容,然后通过将其添加到 Queue 来执行它。当您将命令缓冲区提交到队列时,它将开始在 GPU 端执行。您可以使用工具来控制该执行何时完成。如果您将多个命令缓冲区提交到不同的队列,则它们可能会并行执行。
Vulkan 中没有帧的概念。这意味着您的渲染方式完全取决于您。唯一重要的是您何时必须将帧显示到屏幕上,这通过交换链完成。但是,渲染然后通过网络发送图像,或将图像保存到文件中,或通过交换链将其显示到屏幕上之间没有根本区别。
这意味着可以在完全无头模式下使用 Vulkan,其中没有任何内容显示在屏幕上。您可以渲染图像,然后将它们存储到磁盘上(对于测试非常有用!),或者使用 Vulkan 作为执行 GPU 计算(如光线追踪器或其他计算任务)的方式。
下一步:Vulkan 渲染流程