试想一下,有一天你被要求为最先进的图形硬件设计一款API,要求这款API具有尽可能高的效率,同时支持立即渲染架构和瓷块渲染架构,与所有主要的操作系统兼容...
  试想一下,有一天你被要求为最先进的图形硬件设计一款API,要求这款API具有尽可能高的效率,同时支持立即渲染架构和瓷块渲染架构,与所有主要的操作系统兼容,另外提供可匹敌市场上竞争API的功能。我们可以不断增加越来越多的功能,但还是无法满足消费者没有尽头的要求。

好吧,我们有一些令人兴奋的消息与大家分享。今天早些时候,Khronos Group批准了Vulkan 1.0 规范。这款全新API不仅满足了我上面提到的期望,同时也为全球各地开发人员和图形工程师带来了巨大的,全新的可能性。这款全新API源自AMD Mantle API,并且经过业界IHVISV专家进一步调整,成为独树一帜的图形API。举例来说,为了减少冗余调用,以及渲染管线气泡产生(经常导致帧速率产生离奇的波动)的可能性,3D应用程序无需再为每帧画面进行上千次API调用。相反,通过利用新的工具,如命令缓冲3D应用程序有望提前制备相关数据,只需进行一次调用即可。

多线程渲染就在此地

                 Vulkan问世之前的线程模型

                      Vulkan线程模型

制备(Baking)是一个有趣的概念,但是如果进程被限制在一个特定的线程当,就很容易变成性能瓶颈,幸运的是,借助Vulkan,应用程序不再被限制在单线程渲染环境中,它们无需再被迫执行昂贵的线程间同步。借助这款全新API,应用程序可以自由地从它们想要的任何线程当中发送API调用,只要它遵循对象访问同步要求即可。换句话说,Vulkan已经在其规范当中清楚地说明,CPU可以同时运行的线程越多,GPU就可以更快地开始绘制帧 只要Vulkan应用程序在所有可用的CPU核心当中分配制备过程。

API中提供多线程支持,只是硬币的一面。VulkanGPU上也推出了类似的概念。借助AMD GCN架构和新的API,开发人员获得直接访问GPU能力,可以将GPU工作分配到不同的命令队列。这意味着你可以有一个队列负责物理运算工作,而另外一个队列在进行光栅化工作。我之前已经提到,保持GPU始终处于繁忙状态,有助于避免产生所谓的管线气泡 -这对实现最佳渲染性能是至关重要的。

调整运行时的验证程度

还应当强调的是,Vulkan API是明确的,这意味着每个API调用发出所需的验证量被减少到最低限度。例如,如果你的应用程序有一个大胆的举动,尝试使用一个已经释放的对象,或者试图发出一个规范不允许的绘制调用,没准GPU就会崩溃或挂起。该API设计师们深知在这种新设计当中应用程序是多么容易犯这样的错误,但他们也知道验证每帧对API的调用是否正确,要花费多少时间。为了调和这两个世界,设计者设计了验证层,可以在Runtime当中选择启用,类似于GL_ARB_debug_output,该信息通过回调传递,可以提供有关关键错误的信息 – 可以作为提升性能的潜在途径 - 或者干脆提供一个警告,该应用程序不符合规范。这意味着结果可能会根据不同的平台有所不同。

Renderpasses

我在前面提到Vulkan API在设计时考虑到千差万别的不同硬件架构。针对这一要求,Vulkan API特别引入了renderpasses这一新概念。renderpass是一种方法,它允许应用程序和驱动程序进行通讯,告诉驱动程序渲染过程将如何进行。驱动程序被事先告知图像要被访问的部分(无论是读取还是修改),以及访问发生的时间和渲染执行的顺序。所有这些信息允许驱动程序推迟缓存刷新,直到真正需要刷新的时刻,也允许驱动程序重新安排渲染过程,让非重叠的渲染彼此交织,在给定的硬件架构和功能上获得最大性能。但是,renderpasse最重要的特性之一是,应用程序现在可以清楚地说明它计划花费的帧时间数量。这个信息需要被制备 - 一旦建立,就可以不被修改。这种限制就为驱动程序级别优化开辟了全新世界,以前的API无法带来这种优化。AMD驱动程序架构师GrahamSellers将在他的Vulkan文章当中详述这种功能。

谈到优化,我们不能忘记那些由驱动程序透明地执行的优化。许多硬件架构支持专有无损的压缩格式,减少输入数据大小,而不影响图像质量。这减少了带宽压力,同时提升性能。以前的API当中,这样的“琐事”细节对开发人员隐藏,因此这有时会导致驱动程序会误判应用程序打算做的事情,对数据进行不必要的压缩和解压缩。开发者没有简单的方法来避免这些情况,因为命令已在每帧的基础上提交了那里,驱动程序根本没有办法知道下一个命令是什么,它只能进行有效的猜测!在Vulkan API当中,这种情况已经不复存在。开发者现在必须“照料图像数据在所谓图像布局当中的转换,它涉及到图像被转换到布局之后的操作。同时,布局可以(但不必)对应于指定情况下图像数据的硬件最佳表示。在某些架构当中,该转换过程将要被转换为NOP指令,但在其它架构当中,它们会导致实际的操作。这又是我们建议您始终在开发时使用验证层的一个理由。

Renderpasses过程
SPIR-V

Vulkan当中引入的另一个重要特点是SPIR-V,为计算和图形着色引入的一种二进制中间语言。因为过去没有可参考的GLSL编译器,每个硬件供应商不得不以它自己的方式来达成这一目标,这往往导致到一个畸形着色,在供应商A的驱动程序当中可以成功编译,但供应商B的硬件却拒绝编译。SPIR-V通过采用二进制格式解决了这个问题,和GLSL相比,二进制格式无需考虑不同厂商的不同硬件,也不会被规范误判。它的指令集是通用的,所有的GPU架构均可以对其支持,并且驱动程序在转换SPIR-V表现到硬件IL之时,可以对其应用针对特定硬件的优化。SPIR-V的另一个特点是混淆支持,类似于在比较C和其对等物时发生的状况。最后,SPIR-V编译速度更快,因为驱动程序不再需要解析着色器的文字表述。

当然,Khronos不期望任何人采用SPIR-V操作码编写着色程代码。值得庆幸的是,这些都早已不复存在。 Khronos推荐了一个特殊的工具,叫做glslangvalidator它提供了一种方法,可以将GLSL着色转换成SPIR-V。这款工具程序可以很容易地集成到开发者的创作管线当中,以打造SPIR-V Blob,作为前置或后置步骤,也可以静态链接到开发者的产品当中,在运行时当中执行转换过程。

欢迎社区

Vulkan其它令人兴奋的地方在于,开发者社区在API建立过程当中密切参与,这是从来没有过的事情。除了我前面提到的,任何人都可以使用的开源版glslangvalidator和验证层之外,Khronos又向前迈进一步,也提供了Vulkan一致性测试套件。任何人均可以在Vulkan驱动程序当中用其验证API支持,或进行新的测试,这是让社区随着时间的推移提高驱动程序质量的新方法。

这些都只是这款API的一部分新功能。一篇文章无法面面俱到所有的功能。我们试图在这篇文章中强调的是,Vulkan勇敢地打破了向后兼容的概念,OpenGLOpenGL ES在这方面已经很出名了。我们相信,Vulkan是向前迈出的重要一步;Vulkan API更轻更快,很好地映射了现有的硬件架构。它是便携设备上性能要求极高的应用和游戏的最佳选择,可以带来更好图形质量和帧速率。

一些厂商认为VulkanOpenGL可以融合,其实并不尽然。任何将异步着色等功能和具有启发式本质的OpenGL驱动程序合并的企图,都是注定无法提供最大性能。让我们不要忘记,Vulkan API研发过程当中首要考虑的就是渲染效率!正是出于这个原因,我们认为从头开始编写Vulkan应用程序才是正道,而不是试图在一个应用程序中混合两种APIOpenGL在各个方面的定义都比较松散,以支持不同硬件架构,这是一个众所周知的事实,它如何与Vulkan互动?我们可以想象开发人员花费大量时间调试OpenGLVulkan的混合代码,另外这种方式在不同的平台上执行也有不同的结果。走这条道路可能适用于短期开发,但绝对不是长期项目的选择。