启用扩展

本节介绍启用扩展的逻辑。

两种类型的扩展

扩展分为两组,实例扩展设备扩展。 简而言之,实例扩展与整个 VkInstance 相关联,而设备扩展仅与单个 VkDevice 对象相关联。

此信息记录在每个扩展参考页的“扩展类型”部分下。 以下示例

enabling_extensions_instance_extension.png

检查支持

应用程序可以首先查询物理设备,以使用 vkEnumerateInstanceExtensionPropertiesvkEnumerateDeviceExtensionProperties 检查扩展是否受支持

// Simple example
uint32_t count = 0;
vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &count, nullptr);
std::vector<VkExtensionProperties> extensions(count);
vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &count, extensions.data());

// Checking for support of VK_KHR_bind_memory2
for (uint32_t i = 0; i < count; i++) {
    if (strcmp(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME, extensions[i].extensionName) == 0) {
        break; // VK_KHR_bind_memory2 is supported
    }
}

启用扩展

即使实现支持该扩展,除非在 VkInstanceVkDevice 创建时启用该扩展,否则使用该扩展的功能是未定义的行为

以下是启用诸如 VK_KHR_driver_properties 之类的扩展所需的一个示例。

enabling_extensions_driver_properties.png
// VK_KHR_get_physical_device_properties2 is required to use VK_KHR_driver_properties
// since it's an instance extension it needs to be enabled before at VkInstance creation time
std::vector<const char*> instance_extensions;
instance_extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);

VkInstanceCreateInfo instance_create_info  = {};
instance_create_info.enabledExtensionCount   = static_cast<uint32_t>(instance_extensions.size());
instance_create_info.ppEnabledExtensionNames = instance_extensions.data();
vkCreateInstance(&instance_create_info, nullptr, &myInstance);

// ...

std::vector<const char*> device_extensions;
device_extensions.push_back(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME);

VkDeviceCreateInfo device_create_info      = {};
device_create_info.enabledExtensionCount   = static_cast<uint32_t>(device_extensions.size());
device_create_info.ppEnabledExtensionNames = device_extensions.data();
vkCreateDevice(physicalDevice, &device_create_info, nullptr, &myDevice);

检查特性位

重要的是要记住,扩展为 Vulkan 规范增加了功能的存在,但这并不意味着如果扩展受支持,则可以使用扩展的所有特性。 例如,VK_KHR_8bit_storage 扩展,它在 VkPhysicalDevice8BitStorageFeatures 中公开了 3 个特性。

enabling_extensions_8bit.png

这意味着在启用扩展之后,应用程序仍然需要查询并启用扩展所需的特性。

晋升过程

Vulkan 的次要版本发布时,某些扩展会根据规范定义进行晋升。 晋升的目标是将 Vulkan 工作组确定为广泛支持的扩展功能放入核心 Vulkan 规范中。 有关 Vulkan 版本的更多详细信息,请参见版本章节

一个示例是 VK_KHR_get_physical_device_properties2,它用于大多数其他扩展。 在 Vulkan 1.0 中,应用程序必须先查询对 VK_KHR_get_physical_device_properties2 的支持,然后才能调用诸如 vkGetPhysicalDeviceFeatures2KHR 之类的函数。 从 Vulkan 1.1 开始,保证支持 vkGetPhysicalDeviceFeatures2 函数。

看待晋升的另一种方式是再次以 VK_KHR_8bit_storage 为例。 由于 Vulkan 1.0,一些特性(如 textureCompressionASTC_LDR)不是必须支持的,但是可以在无需启用任何扩展的情况下进行查询。 从 Vulkan 1.2 开始,当 VK_KHR_8bit_storage 晋升为核心时,现在可以在 VkPhysicalDeviceVulkan12Features 中找到 VkPhysicalDevice8BitStorageFeatures 中的所有特性。

晋升行为的变更

重要的是要意识到,对于某些被晋升的扩展,存在细微的差异。 规范描述了晋升可能涉及较小的更改,例如扩展的“特性广告/启用”。 为了最好地描述这种微妙之处,可以将 VK_KHR_8bit_storage 用作一个用例。

Vulkan 规范描述了 Vulkan 1.2 的 VK_KHR_8bit_storage 的变化,其中指出

如果不支持 VK_KHR_8bit_storage 扩展,则着色器模块中对 SPIR-V StorageBuffer8BitAccess 功能的支持是可选的。

这里的“不支持”是指这样一个事实:实现可能支持 Vulkan 1.2+,但是如果应用程序查询 vkEnumerateDeviceExtensionProperties,则 VK_KHR_8bit_storage 可能不在结果中。

  • 如果在 vkEnumerateDeviceExtensionProperties 中找到 VK_KHR_8bit_storage,则保证支持 storageBuffer8BitAccess 特性。

  • 如果vkEnumerateDeviceExtensionProperties 中找到 VK_KHR_8bit_storage,则可能支持 storageBuffer8BitAccess 特性,并且可以通过查询 VkPhysicalDeviceVulkan12Features::storageBuffer8BitAccess 来检查。

可以在规范的版本附录中找到对升级的扩展的所有特性更改的列表。