diff --git a/loader/loader.c b/loader/loader.c index 6102a525d..c03006902 100644 --- a/loader/loader.c +++ b/loader/loader.c @@ -7122,6 +7122,15 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumeratePhysicalDevices(VkInstance in // device_configurations in the settings file. VkResult loader_apply_settings_device_configurations(struct loader_instance *inst, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices) { + 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) { + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + memset(pd_was_added, 0, inst->phys_dev_count_term * sizeof(bool)); + 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; @@ -7177,9 +7186,10 @@ VkResult loader_apply_settings_device_configurations(struct loader_instance *ins *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); pPhysicalDevices[written_output_index++] = (VkPhysicalDevice)inst->phys_devs_term[j]; - loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, "Insert VkPhysicalDevice \"%s\" to the pPhysicalDevices list", - pd_props[j].deviceName); + pd_was_added[j] = true; break; } } @@ -7191,7 +7201,7 @@ VkResult loader_apply_settings_device_configurations(struct loader_instance *ins 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: " - "%x%x%x%x-%x%x-%x%x-%x%x-%x%x%x%x%x%x", + "%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]); } else { @@ -7199,12 +7209,29 @@ VkResult loader_apply_settings_device_configurations(struct loader_instance *ins 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: " - "%x%x%x%x-%x%x-%x%x-%x%x-%x%x%x%x%x%x", + "%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]); } } } + + for (uint32_t j = 0; j < inst->phys_dev_count_term; j++) { + if (!pd_was_added[j]) { + 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); + } + } + + if (written_output_index == 0) { + loader_log(inst, VULKAN_LOADER_WARN_BIT, 0, + "loader_apply_settings_device_configurations: None of the settings file device configurations had " + "deviceUUID's that corresponded to enumerated VkPhysicalDevices. Returning VK_ERROR_INITIALIZATION_FAILED"); + return VK_ERROR_INITIALIZATION_FAILED; + } + *pPhysicalDeviceCount = written_output_index; // update with how many were written return VK_SUCCESS; } diff --git a/loader/settings.c b/loader/settings.c index cc6a60c24..5d15e4964 100644 --- a/loader/settings.c +++ b/loader/settings.c @@ -306,6 +306,11 @@ VkResult parse_device_configuration(const struct loader_instance* inst, cJSON* d res = VK_ERROR_INITIALIZATION_FAILED; goto out; } + + if (deviceUUID_array->type != cJSON_Array) { + res = VK_ERROR_INITIALIZATION_FAILED; + goto out; + } if (VK_UUID_SIZE != loader_cJSON_GetArraySize(deviceUUID_array)) { res = VK_ERROR_INITIALIZATION_FAILED; goto out; @@ -368,10 +373,13 @@ VkResult parse_device_configurations(const struct loader_instance* inst, cJSON* res = VK_ERROR_INITIALIZATION_FAILED; goto out; } - res = parse_device_configuration(inst, device, &(loader_settings->device_configurations[i++])); - if (VK_SUCCESS != res) { + res = parse_device_configuration(inst, device, &(loader_settings->device_configurations[i])); + if (res == VK_ERROR_OUT_OF_HOST_MEMORY) { goto out; + } else if (res != VK_SUCCESS) { + continue; } + i++; } out: if (res != VK_SUCCESS) { @@ -606,8 +614,12 @@ void log_settings(const struct loader_instance* inst, loader_settings* settings) 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: %x%x%x%x-%x%x-%x%x-%x%x-%x%x%x%x%x%x", id[0], id[1], id[2], + 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]); + if ('\0' != settings->device_configurations[i].deviceName[0]) { + loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "deviceName: %s", settings->device_configurations[i].deviceName); + } } } loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "---------------------------------"); diff --git a/tests/loader_settings_tests.cpp b/tests/loader_settings_tests.cpp index 8c1fcb90d..fae400367 100644 --- a/tests/loader_settings_tests.cpp +++ b/tests/loader_settings_tests.cpp @@ -3302,7 +3302,7 @@ TEST(SettingsFile, MissingDriverConfiguration) { InstWrapper inst{env.vulkan_functions}; inst.CheckCreate(); - auto pd = inst.GetPhysDev(); + inst.GetPhysDev(VK_ERROR_INITIALIZATION_FAILED); } // Three drivers, second on has the matching UUID in the settings file. @@ -3398,3 +3398,168 @@ TEST(SettingsFile, DriverConfigurationsAndAdditionalDrivers) { ASSERT_TRUE(0 == memcmp(vulkan_11_props.deviceUUID, uuids[1].data(), VK_UUID_SIZE * sizeof(uint8_t))); } + +TEST(SettingsFile, InvalidDriverConfigurations) { + FrameworkEnvironment env{}; + std::vector uuids{3, VulkanUUID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}}; + + // Mix up the uuid's so that they are all unique + int count = 1; + for (auto& uuid : uuids) { + std::rotate(uuid.begin(), uuid.begin() + count, uuid.end()); + count++; + } + env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)) + .set_icd_api_version(VK_API_VERSION_1_1) + .add_physical_device(PhysicalDevice{} + .set_api_version(VK_API_VERSION_1_1) + .set_deviceName("regular_driver") + .set_deviceUUID(uuids[0]) + .finish()); + + env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2).set_discovery_type(ManifestDiscoveryType::override_folder)) + .add_physical_device(PhysicalDevice{} + .set_api_version(VK_API_VERSION_1_1) + .set_deviceName("additional_device") + .set_deviceUUID(uuids[2]) + .finish()); + + env.loader_settings.set_file_format_version({1, 0, 0}).add_app_specific_setting( + AppSpecificSettings{} + .set_additional_drivers_use_exclusively(true) + .add_driver_configuration(LoaderSettingsDriverConfiguration{}.set_path(env.get_icd_manifest_path(1))) + .add_device_configuration(LoaderSettingsDeviceConfiguration{}.set_deviceUUID(uuids[1]))); + env.update_loader_settings(env.loader_settings); + + InstWrapper inst{env.vulkan_functions}; + inst.CheckCreate(); + auto pd = inst.GetPhysDev(VK_ERROR_INITIALIZATION_FAILED); +} + +TEST(SettingsFile, DeviceConfigurationReordersAdditionalDrivers) { + FrameworkEnvironment env{}; + std::vector uuids{3, VulkanUUID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}}; + + // Mix up the uuid's so that they are all unique + int count = 1; + for (auto& uuid : uuids) { + std::rotate(uuid.begin(), uuid.begin() + count, uuid.end()); + count++; + } + + env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)) + .set_icd_api_version(VK_API_VERSION_1_1) + .add_physical_device(PhysicalDevice{} + .set_api_version(VK_API_VERSION_1_1) + .set_deviceName("regular_driverA") + .set_deviceUUID(uuids[0]) + .finish()); + env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)) + .set_icd_api_version(VK_API_VERSION_1_1) + .add_physical_device(PhysicalDevice{} + .set_api_version(VK_API_VERSION_1_1) + .set_deviceName("regular_driverB") + .set_deviceUUID(uuids[1]) + .finish()); + + env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2).set_discovery_type(ManifestDiscoveryType::override_folder)) + .set_icd_api_version(VK_API_VERSION_1_1) + .add_physical_device(PhysicalDevice{} + .set_api_version(VK_API_VERSION_1_1) + .set_deviceName("additional_device") + .set_deviceUUID(uuids[2]) + .finish()); + + env.loader_settings.set_file_format_version({1, 0, 0}).add_app_specific_setting( + AppSpecificSettings{} + .add_driver_configuration(LoaderSettingsDriverConfiguration{}.set_path(env.get_icd_manifest_path(2))) + .add_device_configuration(LoaderSettingsDeviceConfiguration{}.set_deviceUUID(uuids[2])) + .add_device_configuration(LoaderSettingsDeviceConfiguration{}.set_deviceUUID(uuids[0])) + .add_device_configuration(LoaderSettingsDeviceConfiguration{}.set_deviceUUID(uuids[1]))); + env.update_loader_settings(env.loader_settings); + { + InstWrapper inst{env.vulkan_functions}; + inst.CheckCreate(); + auto pd = inst.GetPhysDevs(3).at(0); + VkPhysicalDeviceProperties props{}; + env.vulkan_functions.vkGetPhysicalDeviceProperties(pd, &props); + ASSERT_TRUE(string_eq(props.deviceName, "additional_device")); + } + { // do the same check but with 1.1 so we can check that the UUID matches + InstWrapper inst{env.vulkan_functions}; + inst.create_info.set_api_version(VK_API_VERSION_1_1); + inst.CheckCreate(); + auto pd = inst.GetPhysDevs(3).at(0); + VkPhysicalDeviceProperties props{}; + env.vulkan_functions.vkGetPhysicalDeviceProperties(pd, &props); + ASSERT_TRUE(string_eq(props.deviceName, "additional_device")); + + VkPhysicalDeviceVulkan11Properties vulkan_11_props{}; + vulkan_11_props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES; + VkPhysicalDeviceProperties2 props2{}; + props2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; + props2.pNext = &vulkan_11_props; + inst->vkGetPhysicalDeviceProperties2(pd, &props2); + + ASSERT_TRUE(0 == memcmp(vulkan_11_props.deviceUUID, uuids[2].data(), VK_UUID_SIZE * sizeof(uint8_t))); + } +} + +TEST(SettingsFile, DeviceConfigurationReordersExclusiveAdditionalDrivers) { + FrameworkEnvironment env{}; + std::vector uuids{3, VulkanUUID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}}; + + // Mix up the uuid's so that they are all unique + int count = 1; + for (auto& uuid : uuids) { + std::rotate(uuid.begin(), uuid.begin() + count, uuid.end()); + count++; + } + + env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)) + .set_icd_api_version(VK_API_VERSION_1_1) + .add_physical_device(PhysicalDevice{} + .set_api_version(VK_API_VERSION_1_1) + .set_deviceName("regular_driverA") + .set_deviceUUID(uuids[0]) + .finish()); + env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)) + .set_icd_api_version(VK_API_VERSION_1_1) + .add_physical_device(PhysicalDevice{} + .set_api_version(VK_API_VERSION_1_1) + .set_deviceName("regular_driverB") + .set_deviceUUID(uuids[1]) + .finish()); + + env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2).set_discovery_type(ManifestDiscoveryType::override_folder)) + .set_icd_api_version(VK_API_VERSION_1_1) + .add_physical_device(PhysicalDevice{} + .set_api_version(VK_API_VERSION_1_1) + .set_deviceName("additional_device") + .set_deviceUUID(uuids[2]) + .finish()); + + env.loader_settings.set_file_format_version({1, 0, 0}).add_app_specific_setting( + AppSpecificSettings{} + .set_additional_drivers_use_exclusively(true) + .add_driver_configuration(LoaderSettingsDriverConfiguration{}.set_path(env.get_icd_manifest_path(2))) + .add_device_configuration(LoaderSettingsDeviceConfiguration{}.set_deviceUUID(uuids[2]))); + env.update_loader_settings(env.loader_settings); + + InstWrapper inst{env.vulkan_functions}; + inst.create_info.set_api_version(VK_API_VERSION_1_1); + inst.CheckCreate(); + auto pd = inst.GetPhysDev(); + VkPhysicalDeviceProperties props{}; + env.vulkan_functions.vkGetPhysicalDeviceProperties(pd, &props); + ASSERT_TRUE(string_eq(props.deviceName, "additional_device")); + + VkPhysicalDeviceVulkan11Properties vulkan_11_props{}; + vulkan_11_props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES; + VkPhysicalDeviceProperties2 props2{}; + props2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; + props2.pNext = &vulkan_11_props; + inst->vkGetPhysicalDeviceProperties2(pd, &props2); + + ASSERT_TRUE(0 == memcmp(vulkan_11_props.deviceUUID, uuids[2].data(), VK_UUID_SIZE * sizeof(uint8_t))); +}