使用 Vulkan 配置
此示例的源代码可以在 Khronos Vulkan 示例 github 存储库中找到。 |
此示例演示了 Vulkan 配置库 的用法。配置定义了属性、特性、扩展等的常见需求基线,以使 Vulkan 应用程序更具可移植性。您无需在运行时逐个检查应用程序中的所有这些,而是使用配置库来检查所选设备是否支持给定配置的所有要求。如果满足,则使用同一库来创建设备和/或实例。然后,该库负责启用所有必需的特性、扩展等,从而节省了大量常见的样板代码。
我们将在一个使用描述符索引的示例中展示这一点。
该示例使用 VP_KHR_roadmap_2022
配置,该配置为“2022 年或之后不久在主流智能手机、平板电脑、笔记本电脑、游戏机和台式机设备上发布的新型中高端设备”启用了一组基准特性和扩展。有关此配置包含内容的详细信息,请参见 此处。
不使用配置
如果不使用配置库,并且 API 版本没有将其作为核心特性,则必须在设备和/或实例创建时手动启用特性和扩展。这可能如下所示:
VkPhysicalDeviceFeatures enabled_features{};
VkPhysicalDeviceVulkan11Features enabled_features_11{};
VkPhysicalDeviceVulkan12Features enabled_features_12{};
enabled_features.fullDrawIndexUint32 = VK_TRUE;
enabled_features.imageCubeArray = VK_TRUE;
enabled_features.independentBlend = VK_TRUE;
enabled_features.ampleRateShading = VK_TRUE;
enabled_features.rawIndirectFirstInstance = VK_TRUE;
enabled_features.depthClamp = VK_TRUE;
enabled_features.depthBiasClamp = VK_TRUE;
enabled_features.samplerAnisotropy = VK_TRUE;
enabled_features.occlusionQueryPrecise = VK_TRUE;
enabled_features.fragmentStoresAndAtomics = VK_TRUE;
enabled_features.shaderStorageImageExtendedFormats = VK_TRUE;
enabled_features.shaderUniformBufferArrayDynamicIndexing = VK_TRUE;
enabled_features.shaderSampledImageArrayDynamicIndexing = VK_TRUE;
enabled_features.shaderStorageBufferArrayDynamicIndexing = VK_TRUE;
enabled_features.shaderStorageImageArrayDynamicIndexing = VK_TRUE;
...
enabled_features_11.samplerYcbcrConversion = VK_TRUE;
enabled_features_11.pNext = &enabled_features_12;
...
enabled_features_12.samplerMirrorClampToEdge = VK_TRUE;
enabled_features_12.descriptorIndexing = VK_TRUE;
enabled_features_12.shaderUniformTexelBufferArrayDynamicIndexing = VK_TRUE;
...
VkDeviceCreateInfo device_create_info = {};
device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
device_create_info.pNext = &enabled_features_11;
VkResult result = vkCreateDevice(...);
if (!result) {
app_terminate('Could not create device, reason:' + vk_result_str(result));
}
随着每个额外的设备特性,此代码将变得越来越长,因为物理设备特性需要通过 pNext
成员链接起来。
使用配置
使用配置库和一个需要上述所有特性和扩展的配置,可以大大简化此过程:
// Profile to enable
const VpProfileProperties profile_properties = {VP_KHR_ROADMAP_2022_NAME, VP_KHR_ROADMAP_2022_SPEC_VERSION};
// Instance creation
VkBool32 profile_supported;
vpGetInstanceProfileSupport(nullptr, &profile_properties, &profile_supported);
if (!profile_supported) {
app_terminate("The selected profile is not supported!");
}
VkInstanceCreateInfo create_info{};
create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
create_info.ppEnabledExtensionNames = enabled_extensions.data();
create_info.enabledExtensionCount = static_cast<uint32_t>(enabled_extensions.size());
VpInstanceCreateInfo instance_create_info{};
instance_create_info.pEnabledFullProfiles = &profile_properties;
instance_create_info.enabledFullProfileCount = 1;
instance_create_info.pCreateInfo = &create_info;
result = vpCreateInstance(&instance_create_info, nullptr, &vulkan_instance);
// Device creation
std::vector<const char *> enabled_extensions;
enabled_extensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
VkDeviceCreateInfo create_info{VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO};
create_info.pNext = gpu.get_extension_feature_chain();
create_info.pQueueCreateInfos = &queue_create_info;
create_info.queueCreateInfoCount = 1;
create_info.enabledExtensionCount = static_cast<uint32_t>(enabled_extensions.size());
create_info.ppEnabledExtensionNames = enabled_extensions.data();
VkBool32 profile_supported;
vpGetPhysicalDeviceProfileSupport(instance->get_handle(), gpu.get_handle(), &profile_properties, &profile_supported);
if (!profile_supported) {
app_terminate("The selected profile is not supported (error at creating the device)!");
}
VpDeviceCreateInfo deviceCreateInfo{};
deviceCreateInfo.pCreateInfo = &create_info;
deviceCreateInfo.pEnabledFullProfiles = &profile_properties;
deviceCreateInfo.enabledFullProfileCount = 1;
VkResult result = vpCreateDevice(gpu.get_handle(), &deviceCreateInfo, nullptr, &vulkan_device);
这将启用所选配置中定义的所有特性和扩展,包括描述符索引。通过传递实例和/或设备的 pCreateInfo
,您还可以启用不属于配置的其他扩展。
在实例创建时设置适当的 Vulkan 版本

启用设备特性并设置 pNext 链

并启用所有必需的扩展(包括显式请求的扩展)
