From 3c78068ebaea0be0cdade1cf39de858ce6a648e8 Mon Sep 17 00:00:00 2001 From: Caio Oliveira Date: Sat, 4 Oct 2025 10:11:02 -0700 Subject: [PATCH] vulkan: Expand cases where can_get_driver_info is true VK_KHR_driver_properties requires VK_KHR_get_physical_device_properties2 extension. For Vulkan 1.2 both extensions are core, so nothing to do, for Vulkan 1.1, the latter is core, so only need the former. For Vulkan 1.0 both extensions are required. VK_KHR_driver_properties is a device extension that doesn't need to be explicitly enabled here. As long as its supported it can be used in the query on the physical device, before the logical device is created (i.e. before device extensions can be enabled). See https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#fundamentals-validusage-pNext. VK_KHR_get_physical_device_properties2 is an instance extension, required for the previous one. If the application hasn't enabled it, do in its behalf. Also make sure when the extension is used, the KHR version of the symbol is loaded. This fixes `vulkan_driver` option in applications that ask for Vulkan 1.0 (e.g. vkcube) but that the driver does support the extra extensions. --- src/vulkan.cpp | 99 +++++++++++++++++++++++++++++++------------ subprojects/.wraplock | 0 2 files changed, 72 insertions(+), 27 deletions(-) create mode 100644 subprojects/.wraplock diff --git a/src/vulkan.cpp b/src/vulkan.cpp index 826a298b4e..3ba5cb5f02 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -82,6 +82,7 @@ struct instance_data { enum EngineTypes engine; notify_thread notifier; int control_client; + bool has_props2; }; /* Mapped from VkDevice */ @@ -1819,35 +1820,25 @@ static VkResult overlay_CreateDevice( chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext; - std::vector enabled_extensions(pCreateInfo->ppEnabledExtensionNames, - pCreateInfo->ppEnabledExtensionNames + - pCreateInfo->enabledExtensionCount); + bool can_get_driver_info = false; - uint32_t extension_count; - - instance_data->vtable.EnumerateDeviceExtensionProperties(physicalDevice, nullptr, &extension_count, nullptr); - - std::vector available_extensions(extension_count); - instance_data->vtable.EnumerateDeviceExtensionProperties(physicalDevice, nullptr, &extension_count, available_extensions.data()); + // VK_KHR_driver_properties became core in 1.2 + if (instance_data->api_version >= VK_API_VERSION_1_2) { + can_get_driver_info = true; + } else if (instance_data->has_props2) { + uint32_t device_extension_count; + instance_data->vtable.EnumerateDeviceExtensionProperties(physicalDevice, nullptr, &device_extension_count, nullptr); - bool can_get_driver_info = instance_data->api_version < VK_API_VERSION_1_1 ? false : true; + std::vector device_extensions(device_extension_count); + instance_data->vtable.EnumerateDeviceExtensionProperties(physicalDevice, nullptr, &device_extension_count, device_extensions.data()); - // VK_KHR_driver_properties became core in 1.2 - if (instance_data->api_version < VK_API_VERSION_1_2 && can_get_driver_info) { - for (auto& extension : available_extensions) { - if (extension.extensionName == std::string(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME)) { - for (auto& enabled : enabled_extensions) { - if (enabled == std::string(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME)) - goto DONT; - } - enabled_extensions.push_back(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME); - DONT: - goto FOUND; + for (const auto& ext : device_extensions) { + if (ext.extensionName == std::string(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME)) { + can_get_driver_info = true; + break; } } - can_get_driver_info = false; - FOUND:; } VkResult result = fpCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice); @@ -1867,8 +1858,15 @@ static VkResult overlay_CreateDevice( driverProps.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES; driverProps.pNext = nullptr; if (can_get_driver_info) { - VkPhysicalDeviceProperties2 deviceProps = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, &driverProps}; - instance_data->vtable.GetPhysicalDeviceProperties2(device_data->physical_device, &deviceProps); + // In Vulkan 1.0, use the KHR symbol which is guaranteed to be available if extension is. + auto get_props2 = (PFN_vkGetPhysicalDeviceProperties2) fpGetInstanceProcAddr( + instance_data->instance, + instance_data->api_version > VK_VERSION_1_0 ? "vkGetPhysicalDeviceProperties2" + : "vkGetPhysicalDeviceProperties2KHR"); + if (get_props2) { + VkPhysicalDeviceProperties2 deviceProps = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, &driverProps}; + get_props2(device_data->physical_device, &deviceProps); + } } if (!is_blacklisted()) { @@ -1949,11 +1947,60 @@ static VkResult overlay_CreateInstance( // Advance the link info for the next element on the chain chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext; + const uint32_t api_version = pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0; + bool has_props2 = false; + + std::vector modified_extensions(pCreateInfo->enabledExtensionCount); + VkInstanceCreateInfo modified_create_info = {}; + + if (api_version >= VK_API_VERSION_1_1) { + // Part of Vulkan core. + has_props2 = true; + + } else { + for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) { + const char *ext = pCreateInfo->ppEnabledExtensionNames[i]; + modified_extensions[i] = ext; + if (strcmp(ext, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) == 0) { + has_props2 = true; + break; + } + } + + // Enable VK_KHR_get_physical_device_properties2 if the application hasn't yet and + // it is supported. + if (!has_props2) { + PFN_vkEnumerateInstanceExtensionProperties fpEnumerateInstnaceExtensionProperties = + (PFN_vkEnumerateInstanceExtensionProperties)fpGetInstanceProcAddr(NULL, "vkEnumerateInstanceExtensionProperties"); + uint32_t supported_extensions_count; + fpEnumerateInstnaceExtensionProperties(nullptr, &supported_extensions_count, nullptr); + + std::vector supported_extensions(supported_extensions_count); + fpEnumerateInstnaceExtensionProperties(nullptr, &supported_extensions_count, supported_extensions.data()); + + for (const auto& ext : supported_extensions) { + if (strcmp(ext.extensionName, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) == 0) { + has_props2 = true; + break; + } + } + + if (has_props2) { + modified_extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); + modified_create_info = *pCreateInfo; + modified_create_info.enabledExtensionCount = modified_extensions.size(); + modified_create_info.ppEnabledExtensionNames = modified_extensions.data(); + pCreateInfo = &modified_create_info; + } + } + } VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance); if (result != VK_SUCCESS) return result; struct instance_data *instance_data = new_instance_data(*pInstance); + instance_data->api_version = api_version; + instance_data->has_props2 = has_props2; vk_load_instance_commands(instance_data->instance, fpGetInstanceProcAddr, &instance_data->vtable); @@ -1982,8 +2029,6 @@ static VkResult overlay_CreateInstance( instance_data->engineVersion = engineVersion; } - instance_data->api_version = pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0; - return result; } diff --git a/subprojects/.wraplock b/subprojects/.wraplock new file mode 100644 index 0000000000..e69de29bb2