扩展 Vulkan

新的功能可能通过新的扩展或核心的新版本,或者在某些情况下通过扩展的新版本添加到 Vulkan 中。

本章介绍了 Vulkan 如何版本化,不同版本之间的兼容性如何受到影响,以及 Vulkan 工作组遵循的兼容性规则。

实例和设备功能

枚举实例属性或接受 VkInstance 对象作为参数的命令被认为是实例级功能。

VkDevice 对象或 VkDevice 的子对象分派,或将它们中的任何一个作为参数的命令被认为是设备级功能。设备扩展定义的类型也被认为是设备级功能。

VkPhysicalDevice 分派,或接受 VkPhysicalDevice 对象作为参数的命令被认为是实例级或设备级功能,具体取决于该功能是由实例扩展还是设备扩展指定的。

此外,枚举物理设备属性的命令被认为是设备级功能。

应用程序通常使用仅实现实例级功能的加载器与 Vulkan 交互,并将设备级功能传递给系统上完整 Vulkan API 的实现。在某些情况下,由于这些可以独立实现,因此给定安装上的加载器和设备实现可能会支持不同的版本。为了允许这种情况并指出何时发生这种情况,Vulkan 规范分别枚举了设备和实例级功能 - 它们具有独立版本查询

Vulkan 1.0 最初将新的物理设备枚举功能指定为实例级,要求将其包含在实例扩展中。由于设备级功能的能力需要通过物理设备枚举来发现,这导致许多设备扩展也需要实例扩展。为了减轻这种额外的工作,VK_KHR_get_physical_device_properties2(以及随后的 Vulkan 1.1)重新定义了设备级功能以包括物理设备枚举。

核心版本

Vulkan 规范会定期更新,以修复错误并进行澄清。偶尔,新功能会添加到核心中,并且在某些时候,人们期望对 API 进行大的、破坏性的更改。为了向开发人员表明规范如何以及何时进行这些更改,并提供一种识别每组更改的方法,Vulkan API 维护一个版本号。

版本号

Vulkan 版本号包含四个部分,分别指示 Vulkan API 规范的变体、主版本、次版本和补丁版本。

变体 表示实现支持的 Vulkan API 的变体。对于 Vulkan API,这始终为 0。

非零变体表示 API 是 Vulkan API 的变体,应用程序通常需要修改才能针对它运行。变体字段是版本号的后添加部分,在规范的 1.2.175 版本中添加。由于 Vulkan 使用变体 0,因此此更改完全向后兼容先前 Vulkan 实现的版本号格式。此更改添加了新的版本号宏,并弃用了旧宏。对于使用旧格式和宏的现有应用程序,具有非零变体的实现将解码为非常高的 Vulkan 版本。执行适当版本检查的应用程序应可检测到高版本号。

主版本 表示 API 的重大更改,这将包含规范的全新版本。

次版本 表示将新功能纳入核心规范。

补丁版本 表示已将错误修复、澄清和语言改进纳入规范。

关于共享任何相同版本号的 API 版本的兼容性保证记录在核心版本

版本号在 API 中的多个位置使用。在每次使用中,版本号都按如下方式打包成一个 32 位整数

  • 变体是一个 3 位整数,打包在位 31-29 中。

  • 主版本号是一个 7 位整数,打包在位 28-22 中。

  • 次版本号是一个 10 位整数,打包在位 21-12 中。

  • 补丁版本号是一个 12 位整数,打包在位 11-0 中。

VK_API_VERSION_VARIANT 从打包的版本号中提取 API 变体号

// Provided by VK_VERSION_1_0
#define VK_API_VERSION_VARIANT(version) ((uint32_t)(version) >> 29U)

VK_API_VERSION_MAJOR 从打包的版本号中提取 API 主版本号

// Provided by VK_VERSION_1_0
#define VK_API_VERSION_MAJOR(version) (((uint32_t)(version) >> 22U) & 0x7FU)

VK_VERSION_MAJOR 从打包的版本号中提取 API 主版本号

// Provided by VK_VERSION_1_0
// VK_VERSION_MAJOR is deprecated, but no reason was given in the API XML
// DEPRECATED: This define is deprecated. VK_API_VERSION_MAJOR should be used instead.
#define VK_VERSION_MAJOR(version) ((uint32_t)(version) >> 22U)

VK_API_VERSION_MINOR 从打包的版本号中提取 API 次版本号

// Provided by VK_VERSION_1_0
#define VK_API_VERSION_MINOR(version) (((uint32_t)(version) >> 12U) & 0x3FFU)

VK_VERSION_MINOR 从打包的版本号中提取 API 次版本号

// Provided by VK_VERSION_1_0
// VK_VERSION_MINOR is deprecated, but no reason was given in the API XML
// DEPRECATED: This define is deprecated. VK_API_VERSION_MINOR should be used instead.
#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12U) & 0x3FFU)

VK_API_VERSION_PATCH 从打包的版本号中提取 API 补丁版本号

// Provided by VK_VERSION_1_0
#define VK_API_VERSION_PATCH(version) ((uint32_t)(version) & 0xFFFU)

VK_VERSION_PATCH 从打包的版本号中提取 API 补丁版本号

// Provided by VK_VERSION_1_0
// VK_VERSION_PATCH is deprecated, but no reason was given in the API XML
// DEPRECATED: This define is deprecated. VK_API_VERSION_PATCH should be used instead.
#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xFFFU)

VK_MAKE_API_VERSION 构造一个 API 版本号。

// Provided by VK_VERSION_1_0
#define VK_MAKE_API_VERSION(variant, major, minor, patch) \
    ((((uint32_t)(variant)) << 29U) | (((uint32_t)(major)) << 22U) | (((uint32_t)(minor)) << 12U) | ((uint32_t)(patch)))
  • variant 是变体号。

  • major 是主版本号。

  • minor 是次版本号。

  • patch 是补丁版本号。

VK_MAKE_VERSION 构造一个 API 版本号。

// Provided by VK_VERSION_1_0
// VK_MAKE_VERSION is deprecated, but no reason was given in the API XML
// DEPRECATED: This define is deprecated. VK_MAKE_API_VERSION should be used instead.
#define VK_MAKE_VERSION(major, minor, patch) \
    ((((uint32_t)(major)) << 22U) | (((uint32_t)(minor)) << 12U) | ((uint32_t)(patch)))
  • major 是主版本号。

  • minor 是次版本号。

  • patch 是补丁版本号。

VK_API_VERSION_1_0 返回 Vulkan 1.0.0 的 API 版本号。

// Provided by VK_VERSION_1_0
// Vulkan 1.0 version number
#define VK_API_VERSION_1_0 VK_MAKE_API_VERSION(0, 1, 0, 0)// Patch version should always be set to 0

VK_API_VERSION_1_1 返回 Vulkan 1.1.0 的 API 版本号。

// Provided by VK_VERSION_1_1
// Vulkan 1.1 version number
#define VK_API_VERSION_1_1 VK_MAKE_API_VERSION(0, 1, 1, 0)// Patch version should always be set to 0

VK_API_VERSION_1_2 返回 Vulkan 1.2.0 的 API 版本号。

// Provided by VK_VERSION_1_2
// Vulkan 1.2 version number
#define VK_API_VERSION_1_2 VK_MAKE_API_VERSION(0, 1, 2, 0)// Patch version should always be set to 0

VK_API_VERSION_1_3 返回 Vulkan 1.3.0 的 API 版本号。

// Provided by VK_VERSION_1_3
// Vulkan 1.3 version number
#define VK_API_VERSION_1_3 VK_MAKE_API_VERSION(0, 1, 3, 0)// Patch version should always be set to 0

VK_API_VERSION_1_4 返回 Vulkan 1.4.0 的 API 版本号。

// Provided by VK_VERSION_1_4
// Vulkan 1.4 version number
#define VK_API_VERSION_1_4 VK_MAKE_API_VERSION(0, 1, 4, 0)// Patch version should always be set to 0

查询版本支持

实例级功能的版本可以通过调用 vkEnumerateInstanceVersion 来查询。

设备级功能的版本可以通过调用 vkGetPhysicalDevicePropertiesvkGetPhysicalDeviceProperties2 来查询,并以 VkPhysicalDeviceProperties::apiVersion 的形式返回,按照 版本号 中所述进行编码。

图层

当启用图层时,它会将自身插入到 Vulkan 命令的调用链中,该图层对这些命令感兴趣。图层**可以**用于各种任务,这些任务将 Vulkan 的基本行为扩展到规范所要求的范围之外 - 例如调用日志记录、跟踪、验证或提供其他扩展。

例如,不期望实现来检查应用程序使用的枚举值是否在允许的范围内。相反,验证层会进行这些检查并标记问题。这避免了应用程序在生产使用期间的性能损失,因为这些图层在生产中不会被启用。

Vulkan 图层**可以**包装对象句柄(即,向应用程序返回与实现生成的句柄值不同的句柄值)。通常不鼓励这样做,因为它会增加与新扩展不兼容的可能性。验证图层包装句柄是为了跟踪每个对象的正确使用和销毁。有关更多信息,请参阅“Vulkan 加载器接口的体系结构”文档。

要查询可用的图层,请调用

// Provided by VK_VERSION_1_0
VkResult vkEnumerateInstanceLayerProperties(
    uint32_t*                                   pPropertyCount,
    VkLayerProperties*                          pProperties);
  • pPropertyCount 是一个指向整数的指针,该整数与可用或查询的图层属性的数量有关,如下所述。

  • pPropertiesNULL 或指向 VkLayerProperties 结构数组的指针。

如果 pPropertiesNULL,则可用的图层属性数量在 pPropertyCount 中返回。否则,pPropertyCount **必须**指向应用程序设置为 pProperties 数组中元素数量的变量,并且在返回时,该变量将被实际写入 pProperties 的结构数量覆盖。如果 pPropertyCount 小于可用的图层属性数量,则最多会写入 pPropertyCount 个结构,并且会返回 VK_INCOMPLETE 而不是 VK_SUCCESS,以指示并非所有可用的属性都返回了。

可用图层的列表可能由于 Vulkan 实现之外的操作而随时更改,因此两次使用相同参数调用 vkEnumerateInstanceLayerProperties **可能**返回不同的结果,或者检索到不同的 pPropertyCount 值或 pProperties 内容。一旦创建了实例,为该实例启用的图层将继续为该实例的生命周期启用并有效,即使其中一些图层对于将来的实例不可用。

有效使用 (隐式)
  • VUID-vkEnumerateInstanceLayerProperties-pPropertyCount-parameter
    pPropertyCount **必须**是指向 uint32_t 值的有效指针

  • VUID-vkEnumerateInstanceLayerProperties-pProperties-parameter
    如果 pPropertyCount 引用的值不为 0,并且 pProperties 不为 NULL,则 pProperties **必须**是指向 pPropertyCountVkLayerProperties 结构数组的有效指针

返回代码
成功
  • VK_SUCCESS

  • VK_INCOMPLETE

失败
  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_OUT_OF_DEVICE_MEMORY

VkLayerProperties 结构定义如下

// Provided by VK_VERSION_1_0
typedef struct VkLayerProperties {
    char        layerName[VK_MAX_EXTENSION_NAME_SIZE];
    uint32_t    specVersion;
    uint32_t    implementationVersion;
    char        description[VK_MAX_DESCRIPTION_SIZE];
} VkLayerProperties;
  • layerName 是一个包含以 null 结尾的 UTF-8 字符串的 VK_MAX_EXTENSION_NAME_SIZEchar 的数组,该字符串是图层的名称。在 VkInstanceCreateInfo 结构中传递的 ppEnabledLayerNames 数组中使用此名称,以启用实例的此图层。

  • specVersion 是图层写入的 Vulkan 版本,按照版本号中所述进行编码。

  • implementationVersion 是此图层的版本。它是一个整数,随着向后兼容的更改而增加。

  • description 是一个包含以 null 结尾的 UTF-8 字符串的 VK_MAX_DESCRIPTION_SIZEchar 的数组,该字符串提供了应用程序**可以**用来识别图层的其他详细信息。

VK_MAX_EXTENSION_NAME_SIZE 是一个数组的 char 值长度,该数组包含一个图层或扩展名称字符串,如 VkLayerProperties::layerNameVkExtensionProperties::extensionName 和其他查询中所返回。

#define VK_MAX_EXTENSION_NAME_SIZE        256U

VK_MAX_DESCRIPTION_SIZE 是一个数组的 char 值长度,该数组包含一个关于查询的附加描述信息的字符串,如 VkLayerProperties::description 和其他查询中所返回。

#define VK_MAX_DESCRIPTION_SIZE           256U

要启用图层,该图层的名称**应该**在创建 VkInstance 时添加到 VkInstanceCreateInfoppEnabledLayerNames 成员中。

加载器实现可能会提供 Vulkan API 之外的机制来启用特定的层。通过这种机制启用的层是隐式启用的,而通过在 VkInstanceCreateInfoppEnabledLayerNames 成员中包含层名称而启用的层是显式启用的。隐式启用的层在显式启用的层之前加载,因此隐式启用的层更接近应用程序,而显式启用的层更接近驱动程序。除非另有说明,隐式启用和显式启用的层仅在启用方式和加载顺序上有所不同。显式启用一个已隐式启用的层会导致该层作为隐式启用层加载;它不会产生额外的效果。

设备层弃用

本规范的早期版本区分了实例层和设备层。实例层只能拦截对 VkInstanceVkPhysicalDevice 进行操作的命令,但不能拦截 vkCreateDevice。设备层在创建时为单个设备启用,并且只能拦截对该设备或其子对象进行操作的命令。

现在设备专用层已弃用,本规范不再区分实例层和设备层。层在实例创建期间启用,并且能够拦截对该实例或其任何子对象进行操作的所有命令。在弃用时,没有已知的设备专用层,也没有创建设备专用层的令人信服的理由。

为了保持与设备层弃用之前发布的实现兼容,应用程序应该仍然枚举和启用设备层。vkEnumerateDeviceLayerProperties 的行为以及 VkDeviceCreateInfoppEnabledLayerNames 成员的有效使用,最大限度地提高了与为满足先前要求而编写的应用程序的兼容性。

要枚举设备层,请调用

// Provided by VK_VERSION_1_0
VkResult vkEnumerateDeviceLayerProperties(
    VkPhysicalDevice                            physicalDevice,
    uint32_t*                                   pPropertyCount,
    VkLayerProperties*                          pProperties);
  • physicalDevice 是将被查询的物理设备。

  • pPropertyCount 是一个指向与可用或查询的层属性数量相关的整数的指针。

  • pPropertiesNULL 或指向 VkLayerProperties 结构数组的指针。

如果 pPropertiesNULL,则可用的图层属性数量在 pPropertyCount 中返回。否则,pPropertyCount **必须**指向应用程序设置为 pProperties 数组中元素数量的变量,并且在返回时,该变量将被实际写入 pProperties 的结构数量覆盖。如果 pPropertyCount 小于可用的图层属性数量,则最多会写入 pPropertyCount 个结构,并且会返回 VK_INCOMPLETE 而不是 VK_SUCCESS,以指示并非所有可用的属性都返回了。

vkEnumerateDeviceLayerProperties 枚举的层列表必须与为实例启用的层序列完全一致。每个枚举层的 VkLayerProperties 的成员必须与层由 vkEnumerateInstanceLayerProperties 枚举时的属性相同。

由于 Android 上的平台细节,在层发现期间,可以调用 vkEnumerateDeviceLayerProperties,其中 physicalDevice 等于 NULL。此行为仅会被层实现观察到,而不会被底层的 Vulkan 驱动程序观察到。

有效使用 (隐式)
  • VUID-vkEnumerateDeviceLayerProperties-physicalDevice-parameter
    physicalDevice 必须是一个有效的 VkPhysicalDevice 句柄

  • VUID-vkEnumerateDeviceLayerProperties-pPropertyCount-parameter
    pPropertyCount **必须**是指向 uint32_t 值的有效指针

  • VUID-vkEnumerateDeviceLayerProperties-pProperties-parameter
    如果 pPropertyCount 引用的值不为 0,并且 pProperties 不为 NULL,则 pProperties **必须**是指向 pPropertyCountVkLayerProperties 结构数组的有效指针

返回代码
成功
  • VK_SUCCESS

  • VK_INCOMPLETE

失败
  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_OUT_OF_DEVICE_MEMORY

VkDeviceCreateInfoppEnabledLayerNamesenabledLayerCount 成员已弃用,它们的必须值被实现忽略。但是,为了兼容性,只有空的层列表或与实例创建时启用的序列完全匹配的列表才是有效的,并且验证层应该为其他情况发布诊断信息。

无论在 VkDeviceCreateInfo 中提供的已启用层列表如何,设备激活的层序列将与创建父实例时启用的层序列完全一致。

扩展

扩展可能定义新的 Vulkan 命令、结构和枚举。出于编译目的,已注册扩展定义的接口,包括新结构和枚举以及新命令的函数指针类型,在 Khronos 提供的 vulkan_core.h 中与核心 API 一起定义。但是,扩展定义的命令可能不可用于静态链接 - 在这种情况下,应在运行时查询这些命令的函数指针,如 命令函数指针中所述。扩展可能由层以及 Vulkan 实现提供。

由于扩展可能会扩展或更改 Vulkan API 的行为,扩展作者应该将对其扩展的支持添加到 Khronos 验证层。对于其参数已由验证层包装的新命令,这一点尤其重要。有关其他信息,请参阅“Vulkan 加载器接口架构”文档。

要启用实例扩展,可以在创建 VkInstance 时将扩展的名称添加到 VkInstanceCreateInfoppEnabledExtensionNames 成员中。

要启用设备扩展,可以在创建 VkDevice 时将扩展的名称添加到 VkDeviceCreateInfoppEnabledExtensionNames 成员中。

物理设备级功能没有任何启用机制,只要 VkPhysicalDevice 支持由 vkEnumerateDeviceExtensionProperties 确定的设备扩展,就可以使用它。

启用扩展(不再进一步使用该扩展)不会更改核心 Vulkan API 或任何其他扩展公开的功能的行为,只是使使用该扩展定义的命令、枚举和结构有效。

各个命令和结构的“有效使用”部分目前不包含哪些扩展必须启用才能使其使用有效,尽管它们将来可能会这样做。它仅在扩展的有效使用部分中定义。

实例扩展

实例扩展将新的实例级功能添加到 API,而不在核心规范之外。

要查询可用的实例扩展,请调用

// Provided by VK_VERSION_1_0
VkResult vkEnumerateInstanceExtensionProperties(
    const char*                                 pLayerName,
    uint32_t*                                   pPropertyCount,
    VkExtensionProperties*                      pProperties);
  • pLayerNameNULL 或指向命名要从中检索扩展的层的以 null 结尾的 UTF-8 字符串的指针。

  • pPropertyCount 是一个指向与可用或查询的扩展属性数量相关的整数的指针,如下所述。

  • pPropertiesNULL 或指向 VkExtensionProperties 结构数组的指针。

pLayerName 参数为 NULL 时,仅返回 Vulkan 实现或隐式启用层提供的扩展。当 pLayerName 是层名称时,将返回该层提供的实例扩展。

如果 pPropertiesNULL,则在 pPropertyCount 中返回可用的扩展属性的数量。否则,pPropertyCount 必须指向一个由应用程序设置的变量,该变量的值为 pProperties 数组中的元素数量,并且在返回时,该变量将被实际写入到 pProperties 的结构数量覆盖。如果 pPropertyCount 小于可用的扩展属性的数量,则最多会写入 pPropertyCount 个结构,并返回 VK_INCOMPLETE 而不是 VK_SUCCESS,以表明并非所有可用的属性都已返回。

由于可用图层列表可能会在对 vkEnumerateInstanceExtensionProperties 的调用之间发生外部更改,如果一个调用中 pLayerName 可用,但在另一个调用中不可用,则两次调用可能会检索到不同的结果。图层支持的扩展也可能会在两次调用之间发生更改,例如,如果图层实现在这两次调用之间被不同的版本替换。

实现必须不声明任何由于行为差异而不能一起启用的扩展对,或者任何不能针对声明的版本启用的扩展。

有效使用 (隐式)
  • VUID-vkEnumerateInstanceExtensionProperties-pLayerName-parameter
    如果 pLayerName 不为 NULL,则 pLayerName 必须是一个以 null 结尾的 UTF-8 字符串

  • VUID-vkEnumerateInstanceExtensionProperties-pPropertyCount-parameter
    pPropertyCount **必须**是指向 uint32_t 值的有效指针

  • VUID-vkEnumerateInstanceExtensionProperties-pProperties-parameter
    如果 pPropertyCount 引用的值不为 0,且 pProperties 不为 NULL,则 pProperties 必须是指向 pPropertyCountVkExtensionProperties 结构体的有效指针

返回代码
成功
  • VK_SUCCESS

  • VK_INCOMPLETE

失败
  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_OUT_OF_DEVICE_MEMORY

  • VK_ERROR_LAYER_NOT_PRESENT

设备扩展

设备扩展为 API 添加了核心规范之外的新的设备级别功能

要查询给定物理设备可用的扩展,请调用

// Provided by VK_VERSION_1_0
VkResult vkEnumerateDeviceExtensionProperties(
    VkPhysicalDevice                            physicalDevice,
    const char*                                 pLayerName,
    uint32_t*                                   pPropertyCount,
    VkExtensionProperties*                      pProperties);
  • physicalDevice 是将被查询的物理设备。

  • pLayerNameNULL 或指向命名要从中检索扩展的层的以 null 结尾的 UTF-8 字符串的指针。

  • pPropertyCount 是指向一个与可用或查询的扩展属性数量相关的整数的指针,其处理方式与 vkEnumerateInstanceExtensionProperties::pPropertyCount 参数相同。

  • pPropertiesNULL 或指向 VkExtensionProperties 结构数组的指针。

pLayerName 参数为 NULL 时,仅返回 Vulkan 实现或隐式启用的图层提供的扩展。当 pLayerName 是图层的名称时,将返回该图层提供的设备扩展。

实现必须不声明任何由于行为差异而不能一起启用的扩展对,或者任何不能针对声明的版本启用的扩展。

如果此查询声明支持 VK_KHR_ray_tracing_pipeline 扩展,则必须也支持 VK_KHR_pipeline_library 扩展。

声明支持 2022 年路线图 配置文件的实现必须pProperties 中声明 VK_KHR_global_priority 扩展。

声明支持 2024 年路线图 配置文件的实现必须pProperties 中声明以下扩展

由于 Android 上的平台细节,在图层发现期间可能会使用 physicalDevice 等于 NULL 调用 vkEnumerateDeviceExtensionProperties。此行为仅会被图层实现观察到,而不会被底层的 Vulkan 驱动程序观察到。

有效使用 (隐式)
  • VUID-vkEnumerateDeviceExtensionProperties-physicalDevice-parameter
    physicalDevice 必须是一个有效的 VkPhysicalDevice 句柄

  • VUID-vkEnumerateDeviceExtensionProperties-pLayerName-parameter
    如果 pLayerName 不为 NULL,则 pLayerName 必须是一个以 null 结尾的 UTF-8 字符串

  • VUID-vkEnumerateDeviceExtensionProperties-pPropertyCount-parameter
    pPropertyCount **必须**是指向 uint32_t 值的有效指针

  • VUID-vkEnumerateDeviceExtensionProperties-pProperties-parameter
    如果 pPropertyCount 引用的值不为 0,且 pProperties 不为 NULL,则 pProperties 必须是指向 pPropertyCountVkExtensionProperties 结构体的有效指针

返回代码
成功
  • VK_SUCCESS

  • VK_INCOMPLETE

失败
  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_OUT_OF_DEVICE_MEMORY

  • VK_ERROR_LAYER_NOT_PRESENT

VkExtensionProperties 结构定义如下

// Provided by VK_VERSION_1_0
typedef struct VkExtensionProperties {
    char        extensionName[VK_MAX_EXTENSION_NAME_SIZE];
    uint32_t    specVersion;
} VkExtensionProperties;
  • extensionName 是一个包含 VK_MAX_EXTENSION_NAME_SIZEchar 的数组,其中包含以 null 结尾的 UTF-8 字符串,即扩展的名称。

  • specVersion 是此扩展的版本。它是一个整数,随着向后兼容的更改而递增。

VkPhysicalDevice 访问设备级功能

某些设备扩展还增加了对物理设备级别功能的支持。如果通过 vkEnumerateDeviceExtensionProperties 声明了支持给定 VkPhysicalDevice 的所需扩展,则可以使用物理设备级别功能。

VkDevice 访问设备级功能

对于从 VkDeviceVkDevice 的子对象分派的命令,必须vkCreateDevice 中启用设备扩展。

扩展依赖关系

某些扩展依赖于其他扩展或特定的核心 API 版本才能运行。要启用具有依赖关系的扩展,在通过 vkCreateInstance 创建实例或通过 vkCreateDevice 创建设备时,还必须通过相同的 API 机制启用任何所需的扩展。每个具有此类依赖关系的扩展都在总结该扩展的附录中记录了它们。

如果支持某个扩展(如 vkEnumerateInstanceExtensionPropertiesvkEnumerateDeviceExtensionProperties 查询到的那样),则该扩展的所需的扩展必须也支持相同的实例或物理设备。

任何具有实例扩展依赖关系且未被 vkCreateInstance 启用的设备扩展都被视为不受支持,因此必须不被任何实例的 VkPhysicalDevice 子对象的 vkEnumerateDeviceExtensionProperties 返回。实例扩展没有对设备扩展的依赖关系。

如果一个所需的扩展已提升为另一个扩展或核心 API 版本,那么作为一般规则,提升的扩展或核心版本也会满足依赖关系。只要原始扩展所需的任何功能也为提升的扩展或核心版本所需要或启用,情况就如此。但是,在某些情况下,某个扩展在被提升的同时使其某些功能在提升的扩展或核心版本中变为可选。在这种情况下,依赖关系可能不会得到满足。唯一的确定方法是查看图层和扩展以及核心修订附录中对原始依赖关系和提升版本的描述。

vk.xml 中存在描述推广方面的一些元数据,特别是 <extension> 标签的 requirespromotedtodeprecatedby 属性。但是,元数据尚未完全描述这种情况。未来,我们可能会扩展 XML 模式,以描述满足依赖关系的完整扩展和版本集合。如下文 推广 中更详细的讨论所述,当扩展被推广时,并不意味着机械地将扩展 API 替换为相应的推广 API 会以完全相同的方式工作;在运行时得到支持;甚至存在。

兼容性保证(信息性)

本节被标记为非正式的,因为 Vulkan API 的实现没有约束性责任 - 但这些保证是 Vulkan 工作组和使用本规范的开发人员之间的合同。

核心版本

Vulkan 规范的每个主要、次要和补丁版本都提供不同的兼容性保证。

补丁版本

补丁版本的差异表明,已对规范进行了一组错误修复或澄清。在补丁版本中可能会添加由 Vulkan 命令返回的不会影响有效应用程序运行时行为的信息性枚举(例如 VkVendorId)。

对于给定规范的主要版本,规范的补丁版本是严格递增的;如上所述,对规范的任何更改都将导致补丁版本增加 1。补丁版本适用于所有次要版本,即使给定的次要版本不受触发更改的影响。

具有不同补丁版本但具有相同主要版本和次要版本的规范彼此完全兼容 - 使得针对一个规范编写的有效应用程序可以与另一个规范的实现一起工作。

如果补丁版本包含可能对开发人员的期望产生重大影响的错误修复或澄清,这些内容将在更改日志中突出显示。通常,Vulkan 工作组会尽量避免这些类型的更改,而是将其修复在扩展或核心版本中。

次要版本

规范的次要版本的更改表明,新的功能已添加到核心规范中。这通常包括标头中的新接口,并且可能还包括行为更改和错误修复。核心功能可能在次要版本中被弃用,但不会被废弃或删除。

对于给定规范的主要版本,规范的次要版本是严格递增的;如上所述,对规范的任何更改都将导致次要版本增加 1。可以在补丁版本中容纳的更改不会增加次要版本。

次要版本较低的规范与次要版本较高的规范的实现向后兼容,适用于核心功能和使用 KHR 供应商标签发布的扩展。供应商和多供应商扩展不能保证在次要版本之间保持功能正常,尽管通常它们是,但也有少数例外 - 有关更多信息,请参见 废弃

主要版本

规范的主要版本的差异表示一组较大的更改,其中可能包括接口更改、行为更改、删除已弃用的功能以及其他功能的修改、添加或替换。

规范的主要版本是单调递增的;如上所述,对规范的任何更改都将导致主要版本增加。可以在补丁或次要版本中容纳的更改不会增加主要版本。

Vulkan 工作组打算仅在为了实现对 Vulkan API 的重大改进(必然需要破坏兼容性)时才发布规范的新主要版本。

新的主要版本很可能包括要发布的全新版本的规范 - 其中可能包括对次要版本和补丁版本的版本控制语义进行全面修订。因此,规范的补丁和次要版本在主要版本之间没有意义。如果规范的主要版本包含类似的版本控制语义,则预计该主要版本的补丁版本和次要版本将重置为 0。

扩展

KHR 扩展必须能够与任何其他 KHR 扩展一起启用,并且对于超出其要求的最低版本的核心规范的任何次要或补丁版本。多供应商扩展应该能够与任何 KHR 扩展或其他多供应商扩展一起启用,并且对于超出其要求的最低版本的核心规范的任何次要或补丁版本。供应商扩展应该能够与来自同一供应商的任何 KHR 扩展、多供应商扩展或其他供应商扩展一起启用,并且对于超出其要求的最低版本的核心规范的任何次要或补丁版本。供应商扩展可能能够与来自其他供应商的供应商扩展一起启用。

另一个例外情况是,如果供应商或多供应商扩展被核心版本或另一个扩展废弃,这将会在扩展附录中突出显示。

推广

扩展,或扩展的功能,可能被推广到新的API 的核心版本,或更多数量的实现者支持的较新扩展。

在更高版本的 Vulkan 中被推广到核心的扩展中定义的结构和枚举类型,根据该版本及其后续版本中等效的 Vulkan 核心接口定义。这会影响 Vulkan 规范、Vulkan 头文件和相应的 XML 注册表。

当推广扩展功能时,可能会引入小的更改,仅限于以下内容

  • 命名

  • 非侵入式参数更改

  • 功能广告/启用

  • 将结构参数组合成更大的结构

  • 作者 ID 后缀已更改或删除

如果推广了扩展功能,则不保证直接兼容性,但是将代码从原始功能移植到推广的功能应该不需要太多精力。

Vulkan 工作组会努力确保较大的更改被标记为已弃用已废弃,并在必要时可以追溯进行标记。

推广的扩展在其扩展附录中列为已推广,并参考其推广到的位置。

当扩展被推广时,扩展中存在的任何向后兼容性别名都将不会被推广。

作为一个假设的示例,如果 VK_KHR_surface 扩展被推广到未来核心版本的一部分,则该扩展定义的 VK_COLOR_SPACE_SRGB_NONLINEAR_KHR 令牌将被推广为 VK_COLOR_SPACE_SRGB_NONLINEAR。但是,VK_COLORSPACE_SRGB_NONLINEAR_KHR 令牌是 VK_COLOR_SPACE_SRGB_NONLINEAR_KHR 的别名。 VK_COLORSPACE_SRGB_NONLINEAR_KHR 将不会被推广,因为它是一个向后兼容性别名,仅因扩展最初发布时的命名错误而存在。

弃用

当预期用例变得不相关或可以通过其他方式解决时,扩展可能会被标记为已弃用。通常,会有一个新的功能可用,以便在另一个扩展或 API 的核心版本中解决该用例,但这不能保证。

旨在替代已弃用功能的功能不保证兼容性,应用程序可能需要进行大幅修改才能使用新功能。

已弃用的扩展会在其扩展附录中列出,并说明弃用原因和任何相关的功能。

废弃

有时,如果新版本的核心 API 或新的扩展与某个扩展根本不兼容,则该扩展将被标记为废弃。废弃的扩展必须不能与使其废弃的扩展或核心版本一起使用。

已废弃的扩展会在其扩展附录中列出,并参考其被废弃的原因。

别名

当一个扩展被较新的功能提升或弃用时,其部分或全部功能可能会被复制到较新的功能中。为了避免重复所有文档和定义,规范将相同的命令和类型标识为彼此的别名。每个别名都与其所别名的定义一起提及,较旧的别名标记为“等效项”。同一命令的每个别名具有相同的行为,同一类型的每个别名具有相同的含义 - 它们可以在应用程序中互换使用,而不会出现兼容性问题。

对于提升的类型,别名的扩展类型在语义上与新的核心类型相同。C99 头文件只是简单地将较旧的别名typedef到提升的类型。

但是,对于提升的命令别名,存在两个单独的命令定义,因为 C99 ABI 没有办法在不使用宏的情况下别名命令定义。在规范的范围内,调用任何一个命令都会产生相同的行为,并且应该仍然调用实现中的相同路径。调试工具可以使用具有不同调试行为的单独命令;例如,将适当的命令名称写入输出日志。

特殊用途扩展

某些扩展仅用于支持特定目的或特定类别的应用程序。这些扩展被称为“特殊用途扩展”。不符合特殊用途标准的应用程序不建议使用这些扩展。

特殊用途案例受到限制,只有以下定义的用途用于描述扩展

表 1. 扩展特殊用途案例
特殊用途 XML 标签 完整描述

CAD 支持

cadsupport

扩展旨在支持 CAD/CAM 应用程序使用的专门功能。

D3D 支持

d3demulation

扩展旨在通过添加特定于 D3D 的功能来支持 D3D 模拟层和从 D3D 移植的应用程序。

开发人员工具

devtools

扩展旨在支持开发人员工具,如捕获重放库。

调试工具

debugging

扩展旨在供应用程序在调试时使用。

OpenGL / ES 支持

glemulation

扩展旨在通过添加特定于这些 API 的功能来支持 OpenGL 和/或 OpenGL ES 模拟层,以及从这些 API 移植的应用程序。

特殊用途扩展在层 & 扩展附录中每个此类扩展的元数据中标识,使用上面“特殊用途”列中的名称。

特殊用途扩展也在 vk.xml 中使用上面“XML 标签”列中的短名称标识,如注册表模式文档的“API 扩展(extension 标签)”部分所述。