Vulkan 扩展简介

Vulkan 扩展(extension)简介,当实现一个Vulkan应用程序时,作为程序开发者最开始要做的事情,也是最有兴趣的事情,就是了解一下API还有哪些扩展特性、功能以及性能指标。我们可以从中获取一些关键的信息,了解错误反馈,调试以及跟踪指令代码的方法,我们还可以做一些验证的工作。Vulkan是通过层和扩展两个概念来实现这些额外的功能的:

  • layer):层会捕捉当前的Vulkan API并且将自己注入到Vulkan指令的执行链中,使其与指定的层关联在一起。我们通常使用层来进行开发过程当中的验证工作。例如,驱动程序不会检查Vulkan API所传入的参数,所以我们可以通过层来完成输入参数的验证,判断它们正确与否。
  • 扩展extension):扩展提供了额外的功能或者特性,它可能未来会成为标准的一部分,也可能不会。扩展也可以作为设备或实例的一部分存在。扩展指令的链接无法通过静态的方式实现,我们需要首先进行查询,然后动态地将它们链接为函数指针。这些函数指针,以及对应的数据结构和枚举常量有可能已经在头文件vulkan.h中进行了定义。

扩展分类

扩展可以被细分为两种类型:

  • 基于实例(instance-based):这类扩展属于全局功能,不依赖于任何设备,也不需要VkDevice作为输入参数就可以直接访问。
  • 基于设备(device-based):这类扩展与设备是直接相关的,需要一个可用的设备句柄来进行相关功能的操作。

我们建议读者在应用程序的开发阶段总是开启层和扩展,而程序准备正式发布为产品的时候将这些功能关闭。在产品阶段关闭扩展和层的话,应用程序不需要进行不必要的验证操作而产生损耗,因此可以获得更好的执行性能。

在开始进行应用程序开发之前,我们先了解一下Hello World!!!示例代码中所用到的用户自定义类都有哪些,以及它们各有什么作用:

  • 主程序:即Hello World!!!的主程序入口,其中包含了main()函数。程序的主要控制逻辑构建于这个文件当中(main.cpp)。
  • Headers.h:这里包含了我们用到的所有的头文件,包括Vulkan自己的头文件包含代码也会放在这里。
  • VulkanLayerAndExtension:这个类是在VulkanLayerAndExtension.h/.cpp中实现的,它提供了基于实例和基于设备的层/扩展的功能实现。它还提供了程序调试相关的性能参数。
  • VulkanInstance:这个类负责创建Vulkan实例对象,它对于程序的初始化是非常重要的。它主要在程序文件VulkanInstance.h/.cpp中实现。
  • VulkanDeviceVulkanDevice.h/.cpp文件中通过这个类实现了逻辑设备和物理设备的创建操作。每个物理设备都可以包含一个或者多个队列。这个类还负责管理设备队列以及相关的属性信息。

查询层和扩展

下面我们会实现main函数、VulkanApplication类,以及VulkanLayerAndExtension类的代码。现在我们要真正开始Vulkan程序的编写了。我们会首先查询Vulkan中所支持的层。请参照下面的指导步骤进行实现:

  • Vulkan程序开发的第一项工作就是将<vulkan/vulkan.h>添加到头文件Header.h。这里包含了我们最常用到的Vulkan API和结构体的声明。
  • 创建VulkanLayerAndExtension类并声明函数以及变量,如下面的代码所示。读者可以参考代码中的注释文字以了解更多细节:
    Vulkan 扩展简介
  • 当应用程序启动之后,getInstanceLayerProperties()函数负责查询实例/全局的层。它会首先得到层的总数,然后将所有的层信息存储到一个类型为VkLayerProperties的向量组变量中,即下文中的layerProperties。这两步操作(计数和存储)都是通过调用vkEnumerateInstanceLayerProperties()函数来实现的(调用两次)。第一次,我们使用第二个参数调用API,第二个参数为NULL,这样返回第一个参数instanceLayerCount的层计数。第二次,我们不会再向第二个参数传入NULL,而是传入一个VkLayerProperties类型的数组/向量组,从而获取到详细的层属性信息。

Vulkan中大部分的枚举类API都有不止一种功能,这取决于用户输入的参数。我们现在只知道API函数vkEnumerateInstanceLayerProperties,它可以用来获取层数(通过传入一个NULL参数),也可以用来获取层的属性信息并存入数组(传入一个指定数据结构的数组作为参数)。

代码实现

Vulkan 扩展简介

下面给出vkEnumerateInstanceLayerProperties()函数的语法:
Vulkan 扩展简介
vkEnumerateInstanceLayerProperties()函数的参数域见表。
Vulkan 扩展简介

当我们获取了每个层的属性信息之后,我们可以使用这些信息来遍历所有的层并检索各个层可以支持的扩展功能。我们可以通过调用一个用户自定义的函数getExtension-Properties()来实现这一需求。

根据用户对不同的层和扩展执行的结果,控制台可能产生的输出信息如下所示:
Vulkan 扩展简介

每个层都可以支持一个或者多个扩展。我们通过getExtensionProperties()函数首先枚举所有的层,获取扩展的数量。然后,我们将扩展的属性信息保存到数据结构体Layer Properties当中,这里用到了API函数vkEnumerateInstanceExtensionProperties()。整个实现过程很类似于层的枚举过程,即之前的步骤中已经实现过的getInstanceLayerProperties()函数。getExtensionProperties()函数即可以查询基于实例的扩展,也可以查询基于设备的扩展:
Vulkan 扩展简介

Vulkan 扩展简介

酷客网相关文章:

赞(0)

评论 抢沙发

评论前必须登录!