From 898e0fa5058000d3e7258484fd3ab2aa1a016bf0 Mon Sep 17 00:00:00 2001 From: Charles Giessen Date: Fri, 26 Sep 2025 13:35:08 -0500 Subject: [PATCH 1/2] Add utility for getting the string representation of a UUID Allows for the loader_log call to not have 16+ parameters. --- loader/log.c | 7 +++++++ loader/log.h | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/loader/log.c b/loader/log.c index 41b89ee65..78589a47c 100644 --- a/loader/log.c +++ b/loader/log.c @@ -274,3 +274,10 @@ void loader_log_asm_function_not_supported(const struct loader_instance *inst, V const char *func_name) { loader_log(inst, msg_type, msg_code, "Function %s not supported for this physical device", func_name); } + +void loader_log_generate_uuid_string(const uint8_t uuid[16], char output[UUID_STR_LEN]) { + assert(uuid && output); + snprintf(output, UUID_STR_LEN, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", uuid[0], uuid[1], + uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7], uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], + uuid[14], uuid[15]); +} diff --git a/loader/log.h b/loader/log.h index 1b594ab77..6075e1a0a 100644 --- a/loader/log.h +++ b/loader/log.h @@ -83,3 +83,7 @@ void loader_log_asm_function_not_supported(const struct loader_instance *inst, V const char *func_name) ASM_NAME("loader_log_asm_function_not_supported"); #undef ASM_NAME + +#define UUID_STR_LEN 37 // always 32 digits, 4 dashes, and 1 null terminator + +void loader_log_generate_uuid_string(const uint8_t uuid[16], char output[UUID_STR_LEN]); From 66d32bc5413ca4b5f850ab5ac8b86e5aaeed2a1c Mon Sep 17 00:00:00 2001 From: Charles Giessen Date: Fri, 26 Sep 2025 14:23:23 -0500 Subject: [PATCH 2/2] Add driverUUID and driverVersion to settings file device configuration parameters deviceUUID is not sufficient to be able to distinguish VkPhysicalDevices as there can be multiple ICD's that report the same VkPhysicalDevice. This can easily occur when a development build of a driver is present alongside a stable build on a system. driverUUID then helps differentiate ICD's reporting the same VkPhysicalDevice, but isn't sufficient as some drivers use the same driverUUID across all builds (RADV from Mesa as example). Thus, driverVersion is used for that purpose. --- loader/loader.c | 161 +++++++++++++++++++-------- loader/settings.c | 84 ++++++++++---- loader/settings.h | 5 +- tests/framework/icd/test_icd.cpp | 6 + tests/framework/icd/test_icd.h | 1 + tests/framework/test_environment.cpp | 10 ++ tests/framework/test_environment.h | 3 + tests/loader_settings_tests.cpp | 51 +++++++++ 8 files changed, 248 insertions(+), 73 deletions(-) diff --git a/loader/loader.c b/loader/loader.c index 821872174..3e5c2d523 100644 --- a/loader/loader.c +++ b/loader/loader.c @@ -7142,6 +7142,46 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumeratePhysicalDevices(VkInstance in return res; } +VkResult check_physical_device_extensions_for_driver_properties_extension(struct loader_physical_device_term *phys_dev_term, + bool *supports_driver_properties) { + *supports_driver_properties = false; + uint32_t extension_count = 0; + VkResult res = phys_dev_term->this_icd_term->dispatch.EnumerateDeviceExtensionProperties(phys_dev_term->phys_dev, NULL, + &extension_count, NULL); + if (res != VK_SUCCESS || extension_count == 0) { + return VK_SUCCESS; + } + VkExtensionProperties *extension_data = loader_stack_alloc(sizeof(VkExtensionProperties) * extension_count); + if (NULL == extension_data) { + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + + res = phys_dev_term->this_icd_term->dispatch.EnumerateDeviceExtensionProperties(phys_dev_term->phys_dev, NULL, &extension_count, + extension_data); + if (res != VK_SUCCESS) { + return VK_SUCCESS; + } + for (uint32_t j = 0; j < extension_count; j++) { + if (!strcmp(extension_data[j].extensionName, VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME)) { + *supports_driver_properties = true; + return VK_SUCCESS; + } + } + return VK_SUCCESS; +} + +// Helper struct containing the relevant details of a VkPhysicalDevice necessary for applying the loader settings device +// configurations. +typedef struct physical_device_configuration_details { + bool pd_was_added; + bool pd_supports_vulkan_11; + bool pd_supports_driver_properties; + VkPhysicalDeviceProperties properties; + VkPhysicalDeviceIDProperties device_id_properties; + VkPhysicalDeviceDriverProperties driver_properties; + +} physical_device_configuration_details; + // Apply the device_configurations in the settings file to the output VkPhysicalDeviceList. // That means looking up each VkPhysicalDevice's deviceUUID, filtering using that, and putting them in the order of // device_configurations in the settings file. @@ -7150,45 +7190,46 @@ VkResult loader_apply_settings_device_configurations(struct loader_instance *ins loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, "Reordering the output of vkEnumeratePhysicalDevices to match the loader settings device configurations list"); - bool *pd_was_added = loader_stack_alloc(inst->phys_dev_count_term * sizeof(bool)); - if (NULL == pd_was_added) { + physical_device_configuration_details *pd_details = + loader_stack_alloc(inst->phys_dev_count_term * sizeof(physical_device_configuration_details)); + if (NULL == pd_details) { return VK_ERROR_OUT_OF_HOST_MEMORY; } - memset(pd_was_added, 0, inst->phys_dev_count_term * sizeof(bool)); + memset(pd_details, 0, inst->phys_dev_count_term * sizeof(physical_device_configuration_details)); - bool *pd_supports_11 = loader_stack_alloc(inst->phys_dev_count_term * sizeof(bool)); - if (NULL == pd_supports_11) { - return VK_ERROR_OUT_OF_HOST_MEMORY; - } - memset(pd_supports_11, 0, inst->phys_dev_count_term * sizeof(bool)); + for (uint32_t i = 0; i < inst->phys_dev_count_term; i++) { + struct loader_physical_device_term *phys_dev_term = inst->phys_devs_term[i]; - VkPhysicalDeviceProperties *pd_props = loader_stack_alloc(inst->phys_dev_count_term * sizeof(VkPhysicalDeviceProperties)); - if (NULL == pd_props) { - return VK_ERROR_OUT_OF_HOST_MEMORY; - } - memset(pd_props, 0, inst->phys_dev_count_term * sizeof(VkPhysicalDeviceProperties)); + phys_dev_term->this_icd_term->dispatch.GetPhysicalDeviceProperties(phys_dev_term->phys_dev, &pd_details[i].properties); + if (pd_details[i].properties.apiVersion < VK_API_VERSION_1_1) { + // Device isn't eligible for sorting + continue; + } + pd_details[i].pd_supports_vulkan_11 = true; + if (pd_details[i].properties.apiVersion >= VK_API_VERSION_1_2) { + pd_details[i].pd_supports_driver_properties = true; + } - VkPhysicalDeviceVulkan11Properties *pd_vulkan_11_props = - loader_stack_alloc(inst->phys_dev_count_term * sizeof(VkPhysicalDeviceVulkan11Properties)); - if (NULL == pd_vulkan_11_props) { - return VK_ERROR_OUT_OF_HOST_MEMORY; - } - memset(pd_vulkan_11_props, 0, inst->phys_dev_count_term * sizeof(VkPhysicalDeviceVulkan11Properties)); + // If this physical device isn't 1.2, then we need to check if it supports VK_KHR_driver_properties + if (!pd_details[i].pd_supports_driver_properties) { + VkResult res = check_physical_device_extensions_for_driver_properties_extension( + phys_dev_term, &pd_details[i].pd_supports_driver_properties); + if (res == VK_ERROR_OUT_OF_HOST_MEMORY) { + return res; + } + } - for (uint32_t i = 0; i < inst->phys_dev_count_term; i++) { - pd_vulkan_11_props[i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES; + pd_details[i].device_id_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES; + pd_details[i].driver_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES; + if (pd_details[i].pd_supports_driver_properties) { + pd_details[i].device_id_properties.pNext = (void *)&pd_details[i].driver_properties; + } - inst->phys_devs_term[i]->this_icd_term->dispatch.GetPhysicalDeviceProperties(inst->phys_devs_term[i]->phys_dev, - &pd_props[i]); - if (pd_props[i].apiVersion >= VK_API_VERSION_1_1) { - pd_supports_11[i] = true; - VkPhysicalDeviceProperties2 props2 = {0}; - props2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; - props2.pNext = (void *)&pd_vulkan_11_props[i]; - if (inst->phys_devs_term[i]->this_icd_term->dispatch.GetPhysicalDeviceProperties2) { - inst->phys_devs_term[i]->this_icd_term->dispatch.GetPhysicalDeviceProperties2(inst->phys_devs_term[i]->phys_dev, - &props2); - } + VkPhysicalDeviceProperties2 props2 = {0}; + props2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; + props2.pNext = (void *)&pd_details[i].device_id_properties; + if (phys_dev_term->this_icd_term->dispatch.GetPhysicalDeviceProperties2) { + phys_dev_term->this_icd_term->dispatch.GetPhysicalDeviceProperties2(phys_dev_term->phys_dev, &props2); } } @@ -7198,55 +7239,79 @@ VkResult loader_apply_settings_device_configurations(struct loader_instance *ins for (uint32_t i = 0; i < inst->settings.device_configuration_count; i++) { uint8_t *current_deviceUUID = inst->settings.device_configurations[i].deviceUUID; + uint8_t *current_driverUUID = inst->settings.device_configurations[i].driverUUID; bool configuration_found = false; for (uint32_t j = 0; j < inst->phys_dev_count_term; j++) { // Don't compare deviceUUID's if they have nothing, since we require deviceUUID's to effectively sort them. - if (!pd_supports_11[j]) { + if (!pd_details[j].pd_supports_vulkan_11) { continue; } - if (memcmp(current_deviceUUID, pd_vulkan_11_props[j].deviceUUID, sizeof(uint8_t) * VK_UUID_SIZE) == 0) { + if (memcmp(current_deviceUUID, pd_details[j].device_id_properties.deviceUUID, sizeof(uint8_t) * VK_UUID_SIZE) == 0 && + memcmp(current_driverUUID, pd_details[j].device_id_properties.driverUUID, sizeof(uint8_t) * VK_UUID_SIZE) == 0 && + inst->settings.device_configurations[i].driverVersion == pd_details[j].properties.driverVersion) { configuration_found = true; // Catch when there are more device_configurations than space available in the output if (written_output_index >= *pPhysicalDeviceCount) { *pPhysicalDeviceCount = written_output_index; // write out how many were written return VK_INCOMPLETE; } - loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "pPhysicalDevices array index %d is set to \"%s\" ", - written_output_index, pd_props[j].deviceName); + if (pd_details[j].pd_supports_driver_properties) { + loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, + "pPhysicalDevices array index %d is set to \"%s\" (%s, version %d) ", written_output_index, + pd_details[j].properties.deviceName, pd_details[i].driver_properties.driverName, + pd_details[i].properties.driverVersion); + } else { + loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, + "pPhysicalDevices array index %d is set to \"%s\" (driver version %d) ", written_output_index, + pd_details[j].properties.deviceName, pd_details[i].properties.driverVersion); + } pPhysicalDevices[written_output_index++] = (VkPhysicalDevice)inst->phys_devs_term[j]; - pd_was_added[j] = true; + pd_details[j].pd_was_added = true; break; } } if (!configuration_found) { - uint8_t *id = current_deviceUUID; + char device_uuid_str[UUID_STR_LEN] = {0}; + loader_log_generate_uuid_string(current_deviceUUID, device_uuid_str); + char driver_uuid_str[UUID_STR_LEN] = {0}; + loader_log_generate_uuid_string(current_deviceUUID, driver_uuid_str); + // Log that this configuration was missing. - if (inst->settings.device_configurations[i].deviceName[0] != '\0') { + if (inst->settings.device_configurations[i].deviceName[0] != '\0' && + inst->settings.device_configurations[i].driverName[0] != '\0') { + loader_log( + inst, VULKAN_LOADER_WARN_BIT, 0, + "loader_apply_settings_device_configurations: settings file contained device_configuration which does not " + "appear in the enumerated VkPhysicalDevices. Missing VkPhysicalDevice with deviceName: \"%s\", " + "deviceUUID: %s, driverName: %s, driverUUID: %s, driverVersion: %d", + inst->settings.device_configurations[i].deviceName, device_uuid_str, + inst->settings.device_configurations[i].driverName, driver_uuid_str, + inst->settings.device_configurations[i].driverVersion); + } else if (inst->settings.device_configurations[i].deviceName[0] != '\0') { loader_log( inst, VULKAN_LOADER_WARN_BIT, 0, "loader_apply_settings_device_configurations: settings file contained device_configuration which does not " - "appear in the enumerated VkPhysicalDevices. Missing VkPhysicalDevice with deviceName: \"%s\" and deviceUUID: " - "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", - inst->settings.device_configurations[i].deviceName, id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7], - id[8], id[9], id[10], id[11], id[12], id[13], id[14], id[15]); + "appear in the enumerated VkPhysicalDevices. Missing VkPhysicalDevice with deviceName: \"%s\", " + "deviceUUID: %s, driverUUID: %s, driverVersion: %d", + inst->settings.device_configurations[i].deviceName, device_uuid_str, driver_uuid_str, + inst->settings.device_configurations[i].driverVersion); } else { loader_log( inst, VULKAN_LOADER_WARN_BIT, 0, "loader_apply_settings_device_configurations: settings file contained device_configuration which does not " "appear in the enumerated VkPhysicalDevices. Missing VkPhysicalDevice with deviceUUID: " - "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", - id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7], id[8], id[9], id[10], id[11], id[12], id[13], id[14], - id[15]); + "%s, driverUUID: %s, driverVersion: %d", + device_uuid_str, driver_uuid_str, inst->settings.device_configurations[i].driverVersion); } } } for (uint32_t j = 0; j < inst->phys_dev_count_term; j++) { - if (!pd_was_added[j]) { + if (!pd_details[j].pd_was_added) { loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, "VkPhysicalDevice \"%s\" did not appear in the settings file device configurations list, so was not added " "to the pPhysicalDevices array", - pd_props[j].deviceName); + pd_details[j].properties.deviceName); } } diff --git a/loader/settings.c b/loader/settings.c index 365cfb9d0..8ca81728b 100644 --- a/loader/settings.c +++ b/loader/settings.c @@ -297,39 +297,58 @@ VkResult parse_additional_drivers(const struct loader_instance* inst, cJSON* set return res; } -VkResult parse_device_configuration(const struct loader_instance* inst, cJSON* device_configuration_json, - loader_settings_device_configuration* device_configuration) { - (void)inst; - VkResult res = VK_SUCCESS; - cJSON* deviceUUID_array = loader_cJSON_GetObjectItem(device_configuration_json, "deviceUUID"); - if (NULL == deviceUUID_array) { - res = VK_ERROR_INITIALIZATION_FAILED; - goto out; +VkResult parse_uuid_array(cJSON* device_configuration_json, const char* uuid_name, uint8_t uuid[16]) { + cJSON* uuid_array = loader_cJSON_GetObjectItem(device_configuration_json, uuid_name); + if (NULL == uuid_array) { + return VK_ERROR_INITIALIZATION_FAILED; } - if (deviceUUID_array->type != cJSON_Array) { - res = VK_ERROR_INITIALIZATION_FAILED; - goto out; + if (uuid_array->type != cJSON_Array) { + return VK_ERROR_INITIALIZATION_FAILED; } - if (VK_UUID_SIZE != loader_cJSON_GetArraySize(deviceUUID_array)) { - res = VK_ERROR_INITIALIZATION_FAILED; - goto out; + if (VK_UUID_SIZE != loader_cJSON_GetArraySize(uuid_array)) { + return VK_ERROR_INITIALIZATION_FAILED; } cJSON* uuid_field = NULL; size_t i = 0; - cJSON_ArrayForEach(uuid_field, deviceUUID_array) { + cJSON_ArrayForEach(uuid_field, uuid_array) { + if (i >= VK_UUID_SIZE) { + break; + } if (uuid_field->type != cJSON_Number) { - res = VK_ERROR_INITIALIZATION_FAILED; - goto out; + return VK_ERROR_INITIALIZATION_FAILED; } if (uuid_field->valueint < 0 || uuid_field->valueint > 255) { - res = VK_ERROR_INITIALIZATION_FAILED; - goto out; + return VK_ERROR_INITIALIZATION_FAILED; } - device_configuration->deviceUUID[i] = (uint8_t)uuid_field->valueint; + + uuid[i] = (uint8_t)uuid_field->valueint; i++; } + return VK_SUCCESS; +} + +VkResult parse_device_configuration(const struct loader_instance* inst, cJSON* device_configuration_json, + loader_settings_device_configuration* device_configuration) { + (void)inst; + VkResult res = VK_SUCCESS; + + res = parse_uuid_array(device_configuration_json, "deviceUUID", device_configuration->deviceUUID); + if (VK_SUCCESS != res) { + goto out; + } + + res = parse_uuid_array(device_configuration_json, "driverUUID", device_configuration->driverUUID); + if (VK_SUCCESS != res) { + goto out; + } + + cJSON* driverVersion_json = loader_cJSON_GetObjectItem(device_configuration_json, "driverVersion"); + if (NULL == driverVersion_json || driverVersion_json->type != cJSON_Number) { + return VK_ERROR_INITIALIZATION_FAILED; + } + device_configuration->driverVersion = driverVersion_json->valueint; VkResult deviceNameRes = loader_parse_json_string_to_existing_str( device_configuration_json, "deviceName", VK_MAX_PHYSICAL_DEVICE_NAME_SIZE, device_configuration->deviceName); @@ -337,6 +356,13 @@ VkResult parse_device_configuration(const struct loader_instance* inst, cJSON* d res = deviceNameRes; goto out; } + + VkResult driverNameRes = loader_parse_json_string_to_existing_str( + device_configuration_json, "driverName", VK_MAX_PHYSICAL_DEVICE_NAME_SIZE, device_configuration->driverName); + if (VK_ERROR_OUT_OF_HOST_MEMORY == driverNameRes) { + res = driverNameRes; + goto out; + } out: if (res != VK_SUCCESS) { memset(device_configuration, 0, sizeof(loader_settings_device_configuration)); @@ -542,6 +568,10 @@ bool check_if_device_configurations_are_equal(loader_settings_device_configurati for (uint32_t i = 0; i < VK_UUID_SIZE; i++) { if (a->deviceUUID[i] != b->deviceUUID[i]) return false; } + for (uint32_t i = 0; i < VK_UUID_SIZE; i++) { + if (a->driverUUID[i] != b->driverUUID[i]) return false; + } + if (a->driverVersion != b->driverVersion) return false; return true; } @@ -613,13 +643,19 @@ void log_settings(const struct loader_instance* inst, loader_settings* settings) loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Device Configurations count = %d", settings->device_configuration_count); for (uint32_t i = 0; i < settings->device_configuration_count; i++) { loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "---- Device Configuration [%d] ----", i); - uint8_t* id = settings->device_configurations[i].deviceUUID; - loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, - "deviceUUID: %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", id[0], id[1], id[2], - id[3], id[4], id[5], id[6], id[7], id[8], id[9], id[10], id[11], id[12], id[13], id[14], id[15]); + char device_uuid_str[UUID_STR_LEN] = {0}; + loader_log_generate_uuid_string(settings->device_configurations[i].deviceUUID, device_uuid_str); + char driver_uuid_str[UUID_STR_LEN] = {0}; + loader_log_generate_uuid_string(settings->device_configurations[i].driverUUID, driver_uuid_str); + loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "deviceUUID: %s", device_uuid_str); + loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "driverUUID: %s", driver_uuid_str); + loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "driverVersion: %d", settings->device_configurations[i].driverVersion); if ('\0' != settings->device_configurations[i].deviceName[0]) { loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "deviceName: %s", settings->device_configurations[i].deviceName); } + if ('\0' != settings->device_configurations[i].driverName[0]) { + loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "driverName: %s", settings->device_configurations[i].driverName); + } } } loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "---------------------------------"); diff --git a/loader/settings.h b/loader/settings.h index 9ed5c80bf..df3448619 100644 --- a/loader/settings.h +++ b/loader/settings.h @@ -67,8 +67,11 @@ typedef struct loader_settings_driver_configuration { } loader_settings_driver_configuration; typedef struct loader_settings_device_configuration { - char deviceName[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE]; uint8_t deviceUUID[VK_UUID_SIZE]; + uint8_t driverUUID[VK_UUID_SIZE]; + uint32_t driverVersion; + char deviceName[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE]; + char driverName[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE]; } loader_settings_device_configuration; typedef struct loader_settings { diff --git a/tests/framework/icd/test_icd.cpp b/tests/framework/icd/test_icd.cpp index 1cc964c35..56e8b0b2c 100644 --- a/tests/framework/icd/test_icd.cpp +++ b/tests/framework/icd/test_icd.cpp @@ -1231,6 +1231,12 @@ VKAPI_ATTR void VKAPI_CALL test_vkGetPhysicalDeviceProperties2(VkPhysicalDevice if (pNext->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES) { auto* vulkan_11_props = reinterpret_cast(pNext); memcpy(vulkan_11_props->deviceUUID, phys_dev.deviceUUID.data(), VK_UUID_SIZE); + memcpy(vulkan_11_props->driverUUID, phys_dev.driverUUID.data(), VK_UUID_SIZE); + } + if (pNext->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES) { + auto* device_id_props = reinterpret_cast(pNext); + memcpy(device_id_props->deviceUUID, phys_dev.deviceUUID.data(), VK_UUID_SIZE); + memcpy(device_id_props->driverUUID, phys_dev.driverUUID.data(), VK_UUID_SIZE); } if (pNext->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES) { auto* device_driver_props = reinterpret_cast(pNext); diff --git a/tests/framework/icd/test_icd.h b/tests/framework/icd/test_icd.h index 24309f410..4e4fcec0b 100644 --- a/tests/framework/icd/test_icd.h +++ b/tests/framework/icd/test_icd.h @@ -91,6 +91,7 @@ struct PhysicalDevice { DispatchableHandle vk_physical_device; BUILDER_VALUE(std::string, deviceName) BUILDER_VALUE(VulkanUUID, deviceUUID) + BUILDER_VALUE(VulkanUUID, driverUUID) BUILDER_VALUE(VkPhysicalDeviceProperties, properties) BUILDER_VALUE(VkPhysicalDeviceFeatures, features) BUILDER_VALUE(VkPhysicalDeviceMemoryProperties, memory_properties) diff --git a/tests/framework/test_environment.cpp b/tests/framework/test_environment.cpp index 261d21149..cf983d234 100644 --- a/tests/framework/test_environment.cpp +++ b/tests/framework/test_environment.cpp @@ -699,11 +699,21 @@ std::string get_loader_settings_file_contents(const LoaderSettings& loader_setti if (!device.deviceName.empty()) { writer.AddKeyedString("deviceName", device.deviceName); } + if (!device.driverName.empty()) { + writer.AddKeyedString("driverName", device.driverName); + } writer.StartKeyedArray("deviceUUID"); for (const auto& u : device.deviceUUID) { writer.AddInteger(u); } writer.EndArray(); + + writer.StartKeyedArray("driverUUID"); + for (const auto& u : device.driverUUID) { + writer.AddInteger(u); + } + writer.EndArray(); + writer.AddKeyedInteger("driverVersion", device.driverVersion); writer.EndObject(); } writer.EndArray(); diff --git a/tests/framework/test_environment.h b/tests/framework/test_environment.h index 678e88e99..59444b37e 100644 --- a/tests/framework/test_environment.h +++ b/tests/framework/test_environment.h @@ -365,7 +365,10 @@ using VulkanUUID = std::array; struct LoaderSettingsDeviceConfiguration { BUILDER_VALUE(VulkanUUID, deviceUUID) + BUILDER_VALUE(VulkanUUID, driverUUID) + BUILDER_VALUE(uint32_t, driverVersion) BUILDER_VALUE(std::string, deviceName) + BUILDER_VALUE(std::string, driverName) }; // Log files and their associated filter diff --git a/tests/loader_settings_tests.cpp b/tests/loader_settings_tests.cpp index a276bcce5..225af0e31 100644 --- a/tests/loader_settings_tests.cpp +++ b/tests/loader_settings_tests.cpp @@ -3354,6 +3354,57 @@ TEST(SettingsFile, MissingDriverConfiguration) { inst.GetPhysDev(VK_ERROR_INITIALIZATION_FAILED); } +TEST(SettingsFile, DeviceConfigurationWithSameDriver) { + FrameworkEnvironment env{}; + VulkanUUID device_uuid = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + VulkanUUID driver_uuid = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25}; + + auto& icd0 = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).set_icd_api_version(VK_API_VERSION_1_1); + auto& phys_dev_0 = icd0.add_and_get_physical_device(PhysicalDevice() + .set_api_version(VK_API_VERSION_1_2) + .set_deviceUUID(device_uuid) + .set_driverUUID(driver_uuid) + .set_deviceName("foobar") + .finish()); + phys_dev_0.properties.driverVersion = 1000; + std::string("Fake Driver XYZ").copy(phys_dev_0.driver_properties.driverName, VK_MAX_EXTENSION_NAME_SIZE); + + auto& icd1 = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).set_icd_api_version(VK_API_VERSION_1_1); + auto& phys_dev_1 = icd1.add_and_get_physical_device(PhysicalDevice() + .set_api_version(VK_API_VERSION_1_2) + .set_deviceUUID(device_uuid) + .set_driverUUID(driver_uuid) + .set_deviceName("foobar") + .finish()); + phys_dev_1.properties.driverVersion = 30; + std::string("Fake Driver XYZ, but differently named").copy(phys_dev_1.driver_properties.driverName, VK_MAX_EXTENSION_NAME_SIZE); + + env.loader_settings.set_file_format_version({1, 0, 0}).add_app_specific_setting(AppSpecificSettings{}); + + env.loader_settings.app_specific_settings.at(0).device_configurations.clear(); + env.loader_settings.app_specific_settings.at(0).add_device_configuration( + LoaderSettingsDeviceConfiguration{} + .set_deviceUUID(device_uuid) + .set_driverUUID(driver_uuid) + .set_driverVersion(phys_dev_1.properties.driverVersion)); + env.loader_settings.app_specific_settings.at(0).add_device_configuration( + LoaderSettingsDeviceConfiguration{} + .set_deviceUUID(device_uuid) + .set_driverUUID(driver_uuid) + .set_driverVersion(phys_dev_0.properties.driverVersion)); + env.update_loader_settings(env.loader_settings); + + InstWrapper inst{env.vulkan_functions}; + inst.CheckCreate(); + auto phys_devs = inst.GetPhysDevs(2); + VkPhysicalDeviceProperties props1{}; + VkPhysicalDeviceProperties props2{}; + inst->vkGetPhysicalDeviceProperties(phys_devs.at(0), &props1); + inst->vkGetPhysicalDeviceProperties(phys_devs.at(1), &props2); + ASSERT_EQ(props1.driverVersion, phys_dev_1.properties.driverVersion); + ASSERT_EQ(props2.driverVersion, phys_dev_0.properties.driverVersion); +} + // Three drivers, second on has the matching UUID in the settings file. TEST(SettingsFile, DriverConfigurationIgnoresDriverEnvVars) { FrameworkEnvironment env{};