1 /*
2  * Copyright (c) 2021-2023 The Khronos Group Inc.
3  * Copyright (c) 2021-2023 Valve Corporation
4  * Copyright (c) 2021-2023 LunarG, Inc.
5  * Copyright (c) 2021-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
6  * Copyright (c) 2023-2023 RasterGrid Kft.
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a copy
9  * of this software and/or associated documentation files (the "Materials"), to
10  * deal in the Materials without restriction, including without limitation the
11  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12  * sell copies of the Materials, and to permit persons to whom the Materials are
13  * furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice(s) and this permission notice shall be included in
16  * all copies or substantial portions of the Materials.
17  *
18  * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21  *
22  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
23  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
25  * USE OR OTHER DEALINGS IN THE MATERIALS.
26  *
27  * Author: Charles Giessen <charles@lunarg.com>
28  */
29 
30 #include "test_environment.h"
31 
32 // Test case origin
33 // LX = lunar exchange
34 // LVLGH = loader and validation github
35 // LVLGL = loader and validation gitlab
36 // VL = Vulkan Loader github
37 // VVL = Vulkan Validation Layers github
38 
TEST(CreateInstance, BasicRun)39 TEST(CreateInstance, BasicRun) {
40     FrameworkEnvironment env{};
41     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).set_min_icd_interface_version(5);
42 
43     InstWrapper inst{env.vulkan_functions};
44     inst.CheckCreate();
45 }
46 
47 // LX435
TEST(CreateInstance, ConstInstanceInfo)48 TEST(CreateInstance, ConstInstanceInfo) {
49     FrameworkEnvironment env{};
50     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
51     VkInstance inst = VK_NULL_HANDLE;
52     VkInstanceCreateInfo const info = {VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, nullptr, 0, nullptr, 0, nullptr, 0, nullptr};
53     ASSERT_EQ(env.vulkan_functions.vkCreateInstance(&info, VK_NULL_HANDLE, &inst), VK_SUCCESS);
54     // Must clean up
55     env.vulkan_functions.vkDestroyInstance(inst, nullptr);
56 }
57 
58 // VUID-vkDestroyInstance-instance-parameter, VUID-vkDestroyInstance-pAllocator-parameter
TEST(CreateInstance, DestroyInstanceNullHandle)59 TEST(CreateInstance, DestroyInstanceNullHandle) {
60     FrameworkEnvironment env{};
61     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
62     env.vulkan_functions.vkDestroyInstance(VK_NULL_HANDLE, nullptr);
63 }
64 
65 // VUID-vkDestroyDevice-device-parameter, VUID-vkDestroyDevice-pAllocator-parameter
TEST(CreateInstance, DestroyDeviceNullHandle)66 TEST(CreateInstance, DestroyDeviceNullHandle) {
67     FrameworkEnvironment env{};
68     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
69     env.vulkan_functions.vkDestroyDevice(VK_NULL_HANDLE, nullptr);
70 }
71 
72 // VUID-vkCreateInstance-ppEnabledExtensionNames-01388
TEST(CreateInstance, ExtensionNotPresent)73 TEST(CreateInstance, ExtensionNotPresent) {
74     FrameworkEnvironment env{};
75     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
76     {
77         InstWrapper inst{env.vulkan_functions};
78         inst.create_info.add_extension("VK_EXT_validation_features");  // test icd won't report this as supported
79         inst.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
80     }
81     {
82         InstWrapper inst{env.vulkan_functions};
83         inst.create_info.add_extension("Non_existant_extension");  // unknown instance extension
84         inst.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
85     }
86 }
87 
TEST(CreateInstance, LayerNotPresent)88 TEST(CreateInstance, LayerNotPresent) {
89     FrameworkEnvironment env{};
90     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
91     InstWrapper inst{env.vulkan_functions};
92     inst.create_info.add_layer("VK_NON_EXISTANT_LAYER");
93     inst.CheckCreate(VK_ERROR_LAYER_NOT_PRESENT);
94 }
95 
TEST(CreateInstance, LayerPresent)96 TEST(CreateInstance, LayerPresent) {
97     FrameworkEnvironment env{};
98     env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_2}).add_physical_device({});
99 
100     const char* layer_name = "TestLayer";
101     env.add_explicit_layer(
102         ManifestLayer{}.add_layer(
103             ManifestLayer::LayerDescription{}.set_name(layer_name).set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)),
104         "test_layer.json");
105 
106     InstWrapper inst{env.vulkan_functions};
107     inst.create_info.add_layer(layer_name);
108     inst.CheckCreate();
109 }
110 
TEST(CreateInstance, RelativePaths)111 TEST(CreateInstance, RelativePaths) {
112     FrameworkEnvironment env{};
113     env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_2}.set_library_path_type(LibraryPathType::relative)).add_physical_device({});
114 
115     const char* layer_name = "VK_LAYER_TestLayer";
116     env.add_explicit_layer(
117         TestLayerDetails{ManifestLayer{}.add_layer(
118                              ManifestLayer::LayerDescription{}.set_name(layer_name).set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)),
119                          "test_layer.json"}
120             .set_library_path_type(LibraryPathType::relative));
121 
122     InstWrapper inst{env.vulkan_functions};
123     inst.create_info.add_layer(layer_name);
124     inst.CheckCreate();
125 
126     auto layers = inst.GetActiveLayers(inst.GetPhysDev(), 1);
127     ASSERT_TRUE(string_eq(layers.at(0).layerName, layer_name));
128 }
129 
TEST(CreateInstance, ApiVersionBelow1_0)130 TEST(CreateInstance, ApiVersionBelow1_0) {
131     FrameworkEnvironment env{};
132     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).set_min_icd_interface_version(5);
133 
134     DebugUtilsLogger debug_log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
135     InstWrapper inst{env.vulkan_functions};
136     FillDebugUtilsCreateDetails(inst.create_info, debug_log);
137     inst.create_info.api_version = 1;
138     inst.CheckCreate();
139     ASSERT_TRUE(
140         debug_log.find("VkInstanceCreateInfo::pApplicationInfo::apiVersion has value of 1 which is not permitted. If apiVersion is "
141                        "not 0, then it must be "
142                        "greater than or equal to the value of VK_API_VERSION_1_0 [VUID-VkApplicationInfo-apiVersion]"));
143 }
144 
TEST(CreateInstance, ConsecutiveCreate)145 TEST(CreateInstance, ConsecutiveCreate) {
146     FrameworkEnvironment env{};
147     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
148 
149     for (uint32_t i = 0; i < 100; i++) {
150         InstWrapper inst{env.vulkan_functions};
151         inst.CheckCreate();
152     }
153 }
154 
TEST(CreateInstance, ConsecutiveCreateWithoutDestruction)155 TEST(CreateInstance, ConsecutiveCreateWithoutDestruction) {
156     FrameworkEnvironment env{};
157     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
158 
159     std::vector<InstWrapper> instances;
160     for (uint32_t i = 0; i < 100; i++) {
161         instances.emplace_back(env.vulkan_functions);
162         instances.back().CheckCreate();
163     }
164 }
165 
TEST(NoDrivers, CreateInstance)166 TEST(NoDrivers, CreateInstance) {
167     FrameworkEnvironment env{};
168     InstWrapper inst{env.vulkan_functions};
169     inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER);
170 }
171 
TEST(EnumerateInstanceLayerProperties, UsageChecks)172 TEST(EnumerateInstanceLayerProperties, UsageChecks) {
173     FrameworkEnvironment env{};
174     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
175 
176     const char* layer_name_1 = "TestLayer1";
177     const char* layer_name_2 = "TestLayer1";
178 
179     env.add_explicit_layer(
180         ManifestLayer{}.add_layer(
181             ManifestLayer::LayerDescription{}.set_name(layer_name_1).set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)),
182         "test_layer_1.json");
183 
184     env.add_explicit_layer(
185         ManifestLayer{}.add_layer(
186             ManifestLayer::LayerDescription{}.set_name(layer_name_2).set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)),
187         "test_layer_2.json");
188 
189     {  // OnePass
190         VkLayerProperties layer_props[2] = {};
191         uint32_t layer_count = 2;
192         ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceLayerProperties(&layer_count, layer_props));
193         ASSERT_EQ(layer_count, 2U);
194         auto layers = env.GetLayerProperties(2);
195         ASSERT_TRUE(string_eq(layer_name_1, layer_props[0].layerName));
196         ASSERT_TRUE(string_eq(layer_name_2, layer_props[1].layerName));
197     }
198     {  // OnePass
199         uint32_t layer_count = 0;
200         ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceLayerProperties(&layer_count, nullptr));
201         ASSERT_EQ(layer_count, 2U);
202 
203         VkLayerProperties layer_props[2] = {};
204         ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceLayerProperties(&layer_count, layer_props));
205         ASSERT_EQ(layer_count, 2U);
206         ASSERT_TRUE(string_eq(layer_name_1, layer_props[0].layerName));
207         ASSERT_TRUE(string_eq(layer_name_2, layer_props[1].layerName));
208     }
209     {  // PropertyCountLessThanAvailable
210         VkLayerProperties layer_props{};
211         uint32_t layer_count = 1;
212         ASSERT_EQ(VK_INCOMPLETE, env.vulkan_functions.vkEnumerateInstanceLayerProperties(&layer_count, &layer_props));
213         ASSERT_TRUE(string_eq(layer_name_1, layer_props.layerName));
214     }
215 }
216 
TEST(EnumerateInstanceExtensionProperties, UsageChecks)217 TEST(EnumerateInstanceExtensionProperties, UsageChecks) {
218     FrameworkEnvironment env{};
219     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
220 
221     Extension first_ext{"VK_EXT_validation_features"};  // known instance extensions
222     Extension second_ext{"VK_EXT_headless_surface"};
223     env.reset_icd().add_instance_extensions({first_ext, second_ext});
224 
225     {  // One Pass
226         uint32_t extension_count = 6;
227         std::array<VkExtensionProperties, 6> extensions;
228         ASSERT_EQ(VK_SUCCESS,
229                   env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extensions.data()));
230         ASSERT_EQ(extension_count, 6U);  // default extensions + our two extensions
231 
232         EXPECT_TRUE(string_eq(extensions.at(0).extensionName, first_ext.extensionName.c_str()));
233         EXPECT_TRUE(string_eq(extensions.at(1).extensionName, second_ext.extensionName.c_str()));
234         EXPECT_TRUE(string_eq(extensions.at(2).extensionName, VK_EXT_DEBUG_REPORT_EXTENSION_NAME));
235         EXPECT_TRUE(string_eq(extensions.at(3).extensionName, VK_EXT_DEBUG_UTILS_EXTENSION_NAME));
236         EXPECT_TRUE(string_eq(extensions.at(4).extensionName, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME));
237         EXPECT_TRUE(string_eq(extensions.at(5).extensionName, VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME));
238     }
239     {  // Two Pass
240         auto extensions = env.GetInstanceExtensions(6);
241         // loader always adds the debug report & debug utils extensions
242         EXPECT_TRUE(string_eq(extensions.at(0).extensionName, first_ext.extensionName.c_str()));
243         EXPECT_TRUE(string_eq(extensions.at(1).extensionName, second_ext.extensionName.c_str()));
244         EXPECT_TRUE(string_eq(extensions.at(2).extensionName, VK_EXT_DEBUG_REPORT_EXTENSION_NAME));
245         EXPECT_TRUE(string_eq(extensions.at(3).extensionName, VK_EXT_DEBUG_UTILS_EXTENSION_NAME));
246         EXPECT_TRUE(string_eq(extensions.at(4).extensionName, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME));
247         EXPECT_TRUE(string_eq(extensions.at(5).extensionName, VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME));
248     }
249 }
250 
TEST(EnumerateInstanceExtensionProperties, PropertyCountLessThanAvailable)251 TEST(EnumerateInstanceExtensionProperties, PropertyCountLessThanAvailable) {
252     FrameworkEnvironment env{};
253     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
254 
255     uint32_t extension_count = 0;
256     std::array<VkExtensionProperties, 4> extensions;
257     {  // use nullptr for null string
258         ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr));
259         ASSERT_EQ(extension_count, 4U);  // return debug report & debug utils & portability enumeration & direct driver loading
260         extension_count = 1;             // artificially remove one extension
261 
262         ASSERT_EQ(VK_INCOMPLETE,
263                   env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extensions.data()));
264         ASSERT_EQ(extension_count, 1U);
265         // loader always adds the debug report & debug utils extensions
266         ASSERT_TRUE(string_eq(extensions[0].extensionName, "VK_EXT_debug_report"));
267     }
268     {  // use "" for null string
269         ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties("", &extension_count, nullptr));
270         ASSERT_EQ(extension_count, 4U);  // return debug report & debug utils & portability enumeration & direct driver loading
271         extension_count = 1;             // artificially remove one extension
272 
273         ASSERT_EQ(VK_INCOMPLETE,
274                   env.vulkan_functions.vkEnumerateInstanceExtensionProperties("", &extension_count, extensions.data()));
275         ASSERT_EQ(extension_count, 1U);
276         // loader always adds the debug report & debug utils extensions
277         ASSERT_TRUE(string_eq(extensions[0].extensionName, "VK_EXT_debug_report"));
278     }
279 }
280 
TEST(EnumerateInstanceExtensionProperties, FilterUnkownInstanceExtensions)281 TEST(EnumerateInstanceExtensionProperties, FilterUnkownInstanceExtensions) {
282     FrameworkEnvironment env{};
283     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
284 
285     Extension first_ext{"FirstTestExtension"};  // unknown instance extensions
286     Extension second_ext{"SecondTestExtension"};
287     env.reset_icd().add_instance_extensions({first_ext, second_ext});
288     {
289         auto extensions = env.GetInstanceExtensions(4);
290         // loader always adds the debug report & debug utils extensions
291         EXPECT_TRUE(string_eq(extensions.at(0).extensionName, VK_EXT_DEBUG_REPORT_EXTENSION_NAME));
292         EXPECT_TRUE(string_eq(extensions.at(1).extensionName, VK_EXT_DEBUG_UTILS_EXTENSION_NAME));
293         EXPECT_TRUE(string_eq(extensions.at(2).extensionName, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME));
294         EXPECT_TRUE(string_eq(extensions.at(3).extensionName, VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME));
295     }
296     {  // Disable unknown instance extension filtering
297         EnvVarWrapper disable_inst_ext_filter_env_var{"VK_LOADER_DISABLE_INST_EXT_FILTER", "1"};
298 
299         auto extensions = env.GetInstanceExtensions(6);
300         EXPECT_TRUE(string_eq(extensions.at(0).extensionName, first_ext.extensionName.c_str()));
301         EXPECT_TRUE(string_eq(extensions.at(1).extensionName, second_ext.extensionName.c_str()));
302         EXPECT_TRUE(string_eq(extensions.at(2).extensionName, VK_EXT_DEBUG_REPORT_EXTENSION_NAME));
303         EXPECT_TRUE(string_eq(extensions.at(3).extensionName, VK_EXT_DEBUG_UTILS_EXTENSION_NAME));
304         EXPECT_TRUE(string_eq(extensions.at(4).extensionName, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME));
305         EXPECT_TRUE(string_eq(extensions.at(5).extensionName, VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME));
306     }
307 }
308 
TEST(EnumerateDeviceLayerProperties, LayersMatch)309 TEST(EnumerateDeviceLayerProperties, LayersMatch) {
310     FrameworkEnvironment env{};
311     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device("physical_device_0");
312 
313     const char* layer_name = "TestLayer";
314     env.add_explicit_layer(
315         ManifestLayer{}.add_layer(
316             ManifestLayer::LayerDescription{}.set_name(layer_name).set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)),
317         "test_layer.json");
318 
319     InstWrapper inst{env.vulkan_functions};
320     inst.create_info.add_layer(layer_name);
321     inst.CheckCreate();
322 
323     VkPhysicalDevice phys_dev = inst.GetPhysDev();
324     {  // LayersMatch
325         auto layer_props = inst.GetActiveLayers(phys_dev, 1);
326         ASSERT_TRUE(string_eq(layer_props.at(0).layerName, layer_name));
327     }
328     {  // Property count less than available
329         VkLayerProperties layer_props;
330         uint32_t layer_count = 0;
331         ASSERT_EQ(VK_INCOMPLETE, env.vulkan_functions.vkEnumerateDeviceLayerProperties(phys_dev, &layer_count, &layer_props));
332         ASSERT_EQ(layer_count, 0U);
333     }
334 }
335 
TEST(EnumerateDeviceExtensionProperties, DeviceExtensionEnumerated)336 TEST(EnumerateDeviceExtensionProperties, DeviceExtensionEnumerated) {
337     FrameworkEnvironment env{};
338     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device("physical_device_0");
339 
340     std::array<Extension, 2> device_extensions = {Extension{"MyExtension0", 4}, Extension{"MyExtension1", 7}};
341     for (auto& ext : device_extensions) {
342         driver.physical_devices.front().extensions.push_back(ext);
343     }
344     InstWrapper inst{env.vulkan_functions};
345     inst.CheckCreate();
346 
347     uint32_t driver_count = 1;
348     VkPhysicalDevice physical_device;
349     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &driver_count, &physical_device));
350 
351     uint32_t extension_count = 0;
352     ASSERT_EQ(VK_SUCCESS, inst->vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &extension_count, nullptr));
353     ASSERT_EQ(extension_count, device_extensions.size());
354 
355     std::array<VkExtensionProperties, 2> enumerated_device_exts;
356     ASSERT_EQ(VK_SUCCESS, inst->vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &extension_count,
357                                                                      enumerated_device_exts.data()));
358     ASSERT_EQ(extension_count, device_extensions.size());
359     ASSERT_TRUE(device_extensions[0].extensionName == enumerated_device_exts[0].extensionName);
360     ASSERT_TRUE(device_extensions[0].specVersion == enumerated_device_exts[0].specVersion);
361 }
362 
TEST(EnumerateDeviceExtensionProperties, PropertyCountLessThanAvailable)363 TEST(EnumerateDeviceExtensionProperties, PropertyCountLessThanAvailable) {
364     FrameworkEnvironment env{};
365     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device("physical_device_0");
366 
367     std::array<Extension, 2> device_extensions = {Extension{"MyExtension0", 4}, Extension{"MyExtension1", 7}};
368     for (auto& ext : device_extensions) {
369         driver.physical_devices.front().extensions.push_back(ext);
370     }
371     InstWrapper inst{env.vulkan_functions};
372     inst.CheckCreate();
373 
374     uint32_t driver_count = 1;
375     VkPhysicalDevice physical_device;
376     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &driver_count, &physical_device));
377 
378     uint32_t extension_count = 0;
379     ASSERT_EQ(VK_SUCCESS, inst->vkEnumerateDeviceExtensionProperties(physical_device, "", &extension_count, nullptr));
380     ASSERT_EQ(extension_count, device_extensions.size());
381     extension_count -= 1;
382 
383     std::array<VkExtensionProperties, 2> enumerated_device_exts;
384     ASSERT_EQ(VK_INCOMPLETE,
385               inst->vkEnumerateDeviceExtensionProperties(physical_device, "", &extension_count, enumerated_device_exts.data()));
386     ASSERT_EQ(extension_count, device_extensions.size() - 1);
387     ASSERT_TRUE(device_extensions[0].extensionName == enumerated_device_exts[0].extensionName);
388     ASSERT_TRUE(device_extensions[0].specVersion == enumerated_device_exts[0].specVersion);
389 }
390 
TEST(EnumerateDeviceExtensionProperties, ZeroPhysicalDeviceExtensions)391 TEST(EnumerateDeviceExtensionProperties, ZeroPhysicalDeviceExtensions) {
392     FrameworkEnvironment env{};
393     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device({});
394 
395     InstWrapper inst{env.vulkan_functions};
396     inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 1, 0));
397     inst.CheckCreate(VK_SUCCESS);
398 
399     auto phys_dev = inst.GetPhysDev();
400     DeviceWrapper dev{inst};
401     dev.CheckCreate(phys_dev);
402 
403     uint32_t ext_count = 0;
404     ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateDeviceExtensionProperties(phys_dev, nullptr, &ext_count, nullptr));
405     ASSERT_EQ(ext_count, 0U);
406     VkExtensionProperties ext_props{};
407     ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateDeviceExtensionProperties(phys_dev, nullptr, &ext_count, &ext_props));
408     ASSERT_EQ(ext_count, 0U);
409 }
410 
exercise_EnumerateDeviceExtensionProperties(InstWrapper& inst, VkPhysicalDevice physical_device, std::vector<Extension>& exts_to_expect)411 void exercise_EnumerateDeviceExtensionProperties(InstWrapper& inst, VkPhysicalDevice physical_device,
412                                                  std::vector<Extension>& exts_to_expect) {
413     {  // "expected enumeration pattern"
414         uint32_t extension_count = 0;
415         ASSERT_EQ(VK_SUCCESS, inst->vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &extension_count, nullptr));
416         ASSERT_EQ(extension_count, exts_to_expect.size());
417 
418         std::vector<VkExtensionProperties> enumerated_device_exts{extension_count};
419         ASSERT_EQ(VK_SUCCESS, inst->vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &extension_count,
420                                                                          enumerated_device_exts.data()));
421         ASSERT_EQ(extension_count, exts_to_expect.size());
422         for (uint32_t i = 0; i < exts_to_expect.size(); i++) {
423             ASSERT_TRUE(exts_to_expect[i].extensionName == enumerated_device_exts[i].extensionName);
424             ASSERT_EQ(exts_to_expect[i].specVersion, enumerated_device_exts[i].specVersion);
425         }
426     }
427     {  // "Single call pattern"
428         uint32_t extension_count = static_cast<uint32_t>(exts_to_expect.size());
429         std::vector<VkExtensionProperties> enumerated_device_exts{extension_count};
430         ASSERT_EQ(VK_SUCCESS, inst->vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &extension_count,
431                                                                          enumerated_device_exts.data()));
432         ASSERT_EQ(extension_count, exts_to_expect.size());
433         enumerated_device_exts.resize(extension_count);
434 
435         ASSERT_EQ(extension_count, exts_to_expect.size());
436         for (uint32_t i = 0; i < exts_to_expect.size(); i++) {
437             ASSERT_TRUE(exts_to_expect[i].extensionName == enumerated_device_exts[i].extensionName);
438             ASSERT_EQ(exts_to_expect[i].specVersion, enumerated_device_exts[i].specVersion);
439         }
440     }
441     {  // pPropertiesCount == NULL
442         ASSERT_EQ(VK_INCOMPLETE, inst->vkEnumerateDeviceExtensionProperties(physical_device, nullptr, nullptr, nullptr));
443     }
444     {  // 2nd call pass in way more than in reality
445         uint32_t extension_count = std::numeric_limits<uint32_t>::max();
446         ASSERT_EQ(VK_SUCCESS, inst->vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &extension_count, nullptr));
447         ASSERT_EQ(extension_count, exts_to_expect.size());
448 
449         // reset size to a not earthshatteringly large number of extensions
450         extension_count = static_cast<uint32_t>(exts_to_expect.size()) * 4;
451         std::vector<VkExtensionProperties> enumerated_device_exts{extension_count};
452 
453         ASSERT_EQ(VK_SUCCESS, inst->vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &extension_count,
454                                                                          enumerated_device_exts.data()));
455         ASSERT_EQ(extension_count, exts_to_expect.size());
456         for (uint32_t i = 0; i < exts_to_expect.size(); i++) {
457             ASSERT_TRUE(exts_to_expect[i].extensionName == enumerated_device_exts[i].extensionName);
458             ASSERT_EQ(exts_to_expect[i].specVersion, enumerated_device_exts[i].specVersion);
459         }
460     }
461     {  // 2nd call pass in not enough, go through all possible values from 0 to exts_to_expect.size()
462         uint32_t extension_count = std::numeric_limits<uint32_t>::max();
463         ASSERT_EQ(VK_SUCCESS, inst->vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &extension_count, nullptr));
464         ASSERT_EQ(extension_count, exts_to_expect.size());
465         std::vector<VkExtensionProperties> enumerated_device_exts{extension_count};
466         for (uint32_t i = 0; i < exts_to_expect.size() - 1; i++) {
467             extension_count = i;
468             ASSERT_EQ(VK_INCOMPLETE, inst->vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &extension_count,
469                                                                                 enumerated_device_exts.data()));
470             ASSERT_EQ(extension_count, i);
471             for (uint32_t j = 0; j < i; j++) {
472                 ASSERT_TRUE(exts_to_expect[j].extensionName == enumerated_device_exts[j].extensionName);
473                 ASSERT_EQ(exts_to_expect[j].specVersion, enumerated_device_exts[j].specVersion);
474             }
475         }
476     }
477 }
478 
TEST(EnumerateDeviceExtensionProperties, ImplicitLayerPresentNoExtensions)479 TEST(EnumerateDeviceExtensionProperties, ImplicitLayerPresentNoExtensions) {
480     FrameworkEnvironment env{};
481 
482     std::vector<Extension> exts = {Extension{"MyDriverExtension0", 4}, Extension{"MyDriverExtension1", 7},
483                                    Extension{"MyDriverExtension2", 6}, Extension{"MyDriverExtension3", 10}};
484 
485     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2))
486         .add_physical_device("physical_device_0")
487         .physical_devices.at(0)
488         .add_extensions(exts);
489 
490     env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
491                                                          .set_name("implicit_layer_name")
492                                                          .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
493                                                          .set_disable_environment("DISABLE_ME")),
494                            "implicit_test_layer.json");
495 
496     InstWrapper inst{env.vulkan_functions};
497     inst.CheckCreate();
498 
499     exercise_EnumerateDeviceExtensionProperties(inst, inst.GetPhysDev(), exts);
500 }
501 
TEST(EnumerateDeviceExtensionProperties, ImplicitLayerPresentWithExtensions)502 TEST(EnumerateDeviceExtensionProperties, ImplicitLayerPresentWithExtensions) {
503     FrameworkEnvironment env{};
504     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device({});
505 
506     std::vector<Extension> exts;
507     std::vector<ManifestLayer::LayerDescription::Extension> layer_exts;
508     for (uint32_t i = 0; i < 6; i++) {
509         exts.emplace_back(std::string("LayerExtNumba") + std::to_string(i), i + 10);
510         layer_exts.emplace_back(std::string("LayerExtNumba") + std::to_string(i), i + 10);
511     }
512     env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
513                                                          .set_name("implicit_layer_name")
514                                                          .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
515                                                          .set_disable_environment("DISABLE_ME")
516                                                          .add_device_extensions({layer_exts})),
517                            "implicit_test_layer.json");
518     auto& layer = env.get_test_layer();
519     layer.device_extensions = exts;
520 
521     driver.physical_devices.front().extensions.emplace_back("MyDriverExtension0", 4);
522     driver.physical_devices.front().extensions.emplace_back("MyDriverExtension1", 7);
523 
524     exts.insert(exts.begin(), driver.physical_devices.front().extensions.begin(), driver.physical_devices.front().extensions.end());
525 
526     InstWrapper inst{env.vulkan_functions};
527     inst.CheckCreate();
528 
529     VkPhysicalDevice physical_device = inst.GetPhysDev();
530     exercise_EnumerateDeviceExtensionProperties(inst, physical_device, exts);
531 }
532 
TEST(EnumerateDeviceExtensionProperties, ImplicitLayerPresentWithLotsOfExtensions)533 TEST(EnumerateDeviceExtensionProperties, ImplicitLayerPresentWithLotsOfExtensions) {
534     FrameworkEnvironment env{};
535     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device({});
536 
537     std::vector<Extension> exts;
538     std::vector<ManifestLayer::LayerDescription::Extension> layer_exts;
539     for (uint32_t i = 0; i < 26; i++) {
540         exts.emplace_back(std::string("LayerExtNumba") + std::to_string(i), i + 10);
541         layer_exts.emplace_back(std::string("LayerExtNumba") + std::to_string(i), i + 10);
542     }
543     env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
544                                                          .set_name("implicit_layer_name")
545                                                          .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
546                                                          .set_disable_environment("DISABLE_ME")
547                                                          .add_device_extensions({layer_exts})),
548                            "implicit_test_layer.json");
549     auto& layer = env.get_test_layer();
550     layer.device_extensions = exts;
551 
552     driver.physical_devices.front().extensions.emplace_back("MyDriverExtension0", 4);
553     driver.physical_devices.front().extensions.emplace_back("MyDriverExtension1", 7);
554     driver.physical_devices.front().extensions.emplace_back("MyDriverExtension2", 6);
555     driver.physical_devices.front().extensions.emplace_back("MyDriverExtension3", 9);
556 
557     exts.insert(exts.begin(), driver.physical_devices.front().extensions.begin(), driver.physical_devices.front().extensions.end());
558 
559     InstWrapper inst{env.vulkan_functions};
560     inst.CheckCreate();
561 
562     VkPhysicalDevice physical_device = inst.GetPhysDev();
563     exercise_EnumerateDeviceExtensionProperties(inst, physical_device, exts);
564 }
565 
TEST(EnumerateDeviceExtensionProperties, NoDriverExtensionsImplicitLayerPresentWithExtensions)566 TEST(EnumerateDeviceExtensionProperties, NoDriverExtensionsImplicitLayerPresentWithExtensions) {
567     FrameworkEnvironment env{};
568     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device({});
569 
570     std::vector<Extension> exts;
571     std::vector<ManifestLayer::LayerDescription::Extension> layer_exts;
572     for (uint32_t i = 0; i < 6; i++) {
573         exts.emplace_back(std::string("LayerExtNumba") + std::to_string(i), i + 10);
574         layer_exts.emplace_back(std::string("LayerExtNumba") + std::to_string(i), i + 10);
575     }
576     env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
577                                                          .set_name("implicit_layer_name")
578                                                          .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
579                                                          .set_disable_environment("DISABLE_ME")
580                                                          .add_device_extensions({layer_exts})),
581                            "implicit_test_layer.json");
582     auto& layer = env.get_test_layer();
583     layer.device_extensions = exts;
584 
585     InstWrapper inst{env.vulkan_functions};
586     inst.CheckCreate();
587 
588     VkPhysicalDevice physical_device = inst.GetPhysDev();
589     exercise_EnumerateDeviceExtensionProperties(inst, physical_device, exts);
590 }
591 
TEST(EnumerateDeviceExtensionProperties, NoDriverExtensionsImplicitLayerPresentWithLotsOfExtensions)592 TEST(EnumerateDeviceExtensionProperties, NoDriverExtensionsImplicitLayerPresentWithLotsOfExtensions) {
593     FrameworkEnvironment env{};
594     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device({});
595 
596     std::vector<Extension> exts;
597     std::vector<ManifestLayer::LayerDescription::Extension> layer_exts;
598     for (uint32_t i = 0; i < 6; i++) {
599         exts.emplace_back(std::string("LayerExtNumba") + std::to_string(i), i + 10);
600         layer_exts.emplace_back(std::string("LayerExtNumba") + std::to_string(i), i + 10);
601     }
602     env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
603                                                          .set_name("implicit_layer_name")
604                                                          .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
605                                                          .set_disable_environment("DISABLE_ME")
606                                                          .add_device_extensions({layer_exts})),
607                            "implicit_test_layer.json");
608     auto& layer = env.get_test_layer();
609     layer.device_extensions = exts;
610 
611     InstWrapper inst{env.vulkan_functions};
612     inst.CheckCreate();
613 
614     VkPhysicalDevice physical_device = inst.GetPhysDev();
615     exercise_EnumerateDeviceExtensionProperties(inst, physical_device, exts);
616 }
617 
TEST(EnumerateDeviceExtensionProperties, ImplicitLayerPresentWithDuplicateExtensions)618 TEST(EnumerateDeviceExtensionProperties, ImplicitLayerPresentWithDuplicateExtensions) {
619     FrameworkEnvironment env{};
620     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device({});
621 
622     std::vector<Extension> exts;
623     std::vector<ManifestLayer::LayerDescription::Extension> layer_exts;
624     for (uint32_t i = 0; i < 26; i++) {
625         exts.emplace_back(std::string("LayerExtNumba") + std::to_string(i), i + 10);
626         layer_exts.emplace_back(std::string("LayerExtNumba") + std::to_string(i), i + 10);
627     }
628     env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
629                                                          .set_name("implicit_layer_name")
630                                                          .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
631                                                          .set_disable_environment("DISABLE_ME")
632                                                          .add_device_extensions({layer_exts})),
633                            "implicit_test_layer.json");
634     auto& layer = env.get_test_layer();
635     layer.device_extensions = exts;
636 
637     driver.physical_devices.front().extensions.emplace_back("MyDriverExtension0", 4);
638     driver.physical_devices.front().extensions.emplace_back("MyDriverExtension1", 7);
639 
640     driver.physical_devices.front().extensions.insert(driver.physical_devices.front().extensions.end(), exts.begin(), exts.end());
641     exts.emplace_back("MyDriverExtension0", 4);
642     exts.emplace_back("MyDriverExtension1", 7);
643 
644     driver.physical_devices.front().extensions = exts;
645 
646     InstWrapper inst{env.vulkan_functions};
647     inst.CheckCreate();
648 
649     VkPhysicalDevice physical_device = inst.GetPhysDev();
650     exercise_EnumerateDeviceExtensionProperties(inst, physical_device, exts);
651 }
652 
TEST(EnumerateDeviceExtensionProperties, ImplicitLayerPresentWithOnlyDuplicateExtensions)653 TEST(EnumerateDeviceExtensionProperties, ImplicitLayerPresentWithOnlyDuplicateExtensions) {
654     FrameworkEnvironment env{};
655     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device({});
656 
657     std::vector<Extension> exts;
658     std::vector<ManifestLayer::LayerDescription::Extension> layer_exts;
659     for (uint32_t i = 0; i < 26; i++) {
660         exts.emplace_back(std::string("LayerExtNumba") + std::to_string(i), i + 10);
661         layer_exts.emplace_back(std::string("LayerExtNumba") + std::to_string(i), i + 10);
662     }
663     env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
664                                                          .set_name("implicit_layer_name")
665                                                          .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
666                                                          .set_disable_environment("DISABLE_ME")
667                                                          .add_device_extensions({layer_exts})),
668                            "implicit_test_layer.json");
669     auto& layer = env.get_test_layer();
670     layer.device_extensions = exts;
671 
672     driver.physical_devices.front().extensions = exts;
673 
674     InstWrapper inst{env.vulkan_functions};
675     inst.CheckCreate();
676 
677     VkPhysicalDevice physical_device = inst.GetPhysDev();
678     exercise_EnumerateDeviceExtensionProperties(inst, physical_device, exts);
679 }
680 
TEST(EnumeratePhysicalDevices, OneCall)681 TEST(EnumeratePhysicalDevices, OneCall) {
682     FrameworkEnvironment env{};
683     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).set_min_icd_interface_version(5);
684 
685     driver.add_physical_device("physical_device_0");
686     driver.add_physical_device("physical_device_1");
687     driver.add_physical_device("physical_device_2");
688     driver.add_physical_device("physical_device_3");
689 
690     InstWrapper inst{env.vulkan_functions};
691     inst.CheckCreate();
692 
693     uint32_t physical_count = static_cast<uint32_t>(driver.physical_devices.size());
694     uint32_t returned_physical_count = static_cast<uint32_t>(driver.physical_devices.size());
695     std::vector<VkPhysicalDevice> physical_device_handles = std::vector<VkPhysicalDevice>(physical_count);
696     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &returned_physical_count, physical_device_handles.data()));
697     ASSERT_EQ(physical_count, returned_physical_count);
698 }
699 
TEST(EnumeratePhysicalDevices, TwoCall)700 TEST(EnumeratePhysicalDevices, TwoCall) {
701     FrameworkEnvironment env{};
702     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2))
703                        .set_min_icd_interface_version(5)
704                        .add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
705 
706     const uint32_t real_device_count = 2;
707     for (uint32_t i = 0; i < real_device_count; i++) {
708         driver.add_physical_device(std::string("physical_device_") + std::to_string(i));
709         driver.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
710     }
711 
712     InstWrapper inst{env.vulkan_functions};
713     inst.CheckCreate();
714 
715     uint32_t physical_count = static_cast<uint32_t>(driver.physical_devices.size());
716     uint32_t returned_physical_count = 0;
717     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, nullptr));
718     ASSERT_EQ(physical_count, returned_physical_count);
719 
720     std::array<VkPhysicalDevice, real_device_count> physical_device_handles;
721     ASSERT_EQ(VK_SUCCESS,
722               env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, physical_device_handles.data()));
723     ASSERT_EQ(physical_count, returned_physical_count);
724 }
725 
TEST(EnumeratePhysicalDevices, MatchOneAndTwoCallNumbers)726 TEST(EnumeratePhysicalDevices, MatchOneAndTwoCallNumbers) {
727     FrameworkEnvironment env{};
728     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2))
729                        .set_min_icd_interface_version(5)
730                        .add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
731 
732     const uint32_t real_device_count = 3;
733     for (uint32_t i = 0; i < real_device_count; i++) {
734         driver.add_physical_device(std::string("physical_device_") + std::to_string(i));
735         driver.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
736     }
737 
738     InstWrapper inst1{env.vulkan_functions};
739     inst1.CheckCreate();
740 
741     uint32_t physical_count_one_call = static_cast<uint32_t>(driver.physical_devices.size());
742     std::array<VkPhysicalDevice, real_device_count> physical_device_handles_one_call;
743     ASSERT_EQ(VK_SUCCESS,
744               inst1->vkEnumeratePhysicalDevices(inst1, &physical_count_one_call, physical_device_handles_one_call.data()));
745     ASSERT_EQ(real_device_count, physical_count_one_call);
746 
747     InstWrapper inst2{env.vulkan_functions};
748     inst2.CheckCreate();
749 
750     uint32_t physical_count = static_cast<uint32_t>(driver.physical_devices.size());
751     uint32_t returned_physical_count = 0;
752     ASSERT_EQ(VK_SUCCESS, inst2->vkEnumeratePhysicalDevices(inst2, &returned_physical_count, nullptr));
753     ASSERT_EQ(physical_count, returned_physical_count);
754 
755     std::array<VkPhysicalDevice, real_device_count> physical_device_handles;
756     ASSERT_EQ(VK_SUCCESS, inst2->vkEnumeratePhysicalDevices(inst2, &returned_physical_count, physical_device_handles.data()));
757     ASSERT_EQ(real_device_count, returned_physical_count);
758 
759     ASSERT_EQ(physical_count_one_call, returned_physical_count);
760 }
761 
TEST(EnumeratePhysicalDevices, TwoCallIncomplete)762 TEST(EnumeratePhysicalDevices, TwoCallIncomplete) {
763     FrameworkEnvironment env{};
764     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2))
765                        .set_min_icd_interface_version(5)
766                        .add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
767 
768     const uint32_t real_device_count = 2;
769     for (uint32_t i = 0; i < real_device_count; i++) {
770         driver.physical_devices.emplace_back(std::string("physical_device_") + std::to_string(i));
771         driver.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
772     }
773 
774     InstWrapper inst{env.vulkan_functions};
775     inst.CheckCreate();
776 
777     uint32_t physical_count = 0;
778     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &physical_count, nullptr));
779     ASSERT_EQ(physical_count, driver.physical_devices.size());
780 
781     std::array<VkPhysicalDevice, real_device_count> physical;
782 
783     auto temp_ptr = std::unique_ptr<int>(new int());
784     physical[0] = reinterpret_cast<VkPhysicalDevice>(temp_ptr.get());
785     physical[1] = reinterpret_cast<VkPhysicalDevice>(temp_ptr.get());
786 
787     // Use zero for the device count so we can get the VK_INCOMPLETE message and verify nothing was written into physical
788     physical_count = 0;
789     ASSERT_EQ(VK_INCOMPLETE, inst->vkEnumeratePhysicalDevices(inst, &physical_count, physical.data()));
790     ASSERT_EQ(physical_count, 0U);
791     ASSERT_EQ(static_cast<void*>(physical[0]), static_cast<void*>(temp_ptr.get()));
792     ASSERT_EQ(static_cast<void*>(physical[1]), static_cast<void*>(temp_ptr.get()));
793 
794     // Remove one from the physical device count so we can get the VK_INCOMPLETE message
795     physical_count = 1;
796     ASSERT_EQ(VK_INCOMPLETE, inst->vkEnumeratePhysicalDevices(inst, &physical_count, physical.data()));
797     ASSERT_EQ(physical_count, 1U);
798     ASSERT_EQ(static_cast<void*>(physical[1]), static_cast<void*>(temp_ptr.get()));
799 
800     physical_count = 2;
801     std::array<VkPhysicalDevice, real_device_count> physical_2;
802     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &physical_count, physical_2.data()));
803 
804     // Verify that the first physical device shows up in the list of the second ones
805     ASSERT_TRUE(std::find(physical_2.begin(), physical_2.end(), physical[0]) != physical_2.end());
806 }
807 
TEST(EnumeratePhysicalDevices, ZeroPhysicalDevices)808 TEST(EnumeratePhysicalDevices, ZeroPhysicalDevices) {
809     FrameworkEnvironment env{};
810     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
811     InstWrapper inst{env.vulkan_functions};
812     inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 1, 0));
813     inst.CheckCreate(VK_SUCCESS);
814 
815     uint32_t count = 0;
816     ASSERT_EQ(VK_ERROR_INITIALIZATION_FAILED, env.vulkan_functions.vkEnumeratePhysicalDevices(inst, &count, nullptr));
817     ASSERT_EQ(count, 0U);
818 }
819 
TEST(EnumeratePhysicalDevices, ZeroPhysicalDevicesAfterCreateInstance)820 TEST(EnumeratePhysicalDevices, ZeroPhysicalDevicesAfterCreateInstance) {
821     FrameworkEnvironment env{};
822     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1)).set_min_icd_interface_version(5);
823     InstWrapper inst{env.vulkan_functions};
824     inst.create_info.set_api_version(VK_API_VERSION_1_1);
825     inst.CheckCreate();
826     driver.physical_devices.clear();
827 
828     uint32_t physical_device_count = 1000;  // not zero starting value
829     VkPhysicalDevice physical_device{};
830 
831     EXPECT_EQ(VK_ERROR_INITIALIZATION_FAILED, inst->vkEnumeratePhysicalDevices(inst, &physical_device_count, nullptr));
832     EXPECT_EQ(VK_ERROR_INITIALIZATION_FAILED, inst->vkEnumeratePhysicalDevices(inst, &physical_device_count, &physical_device));
833 
834     uint32_t physical_device_group_count = 1000;  // not zero starting value
835     VkPhysicalDeviceGroupProperties physical_device_group_properties{};
836 
837     EXPECT_EQ(VK_ERROR_INITIALIZATION_FAILED, inst->vkEnumeratePhysicalDeviceGroups(inst, &physical_device_group_count, nullptr));
838     EXPECT_EQ(VK_ERROR_INITIALIZATION_FAILED,
839               inst->vkEnumeratePhysicalDeviceGroups(inst, &physical_device_group_count, &physical_device_group_properties));
840 }
841 
TEST(EnumeratePhysicalDevices, CallTwiceNormal)842 TEST(EnumeratePhysicalDevices, CallTwiceNormal) {
843     FrameworkEnvironment env{};
844     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).set_min_icd_interface_version(5);
845 
846     for (size_t i = 0; i < 4; i++) {
847         driver.physical_devices.emplace_back(std::string("physical_device_") + std::to_string(i));
848     }
849 
850     InstWrapper inst{env.vulkan_functions};
851     inst.CheckCreate();
852 
853     // Call twice in a row and make sure nothing bad happened
854     uint32_t physical_count = static_cast<uint32_t>(driver.physical_devices.size());
855     uint32_t returned_physical_count = static_cast<uint32_t>(driver.physical_devices.size());
856     std::vector<VkPhysicalDevice> physical_device_handles_1 = std::vector<VkPhysicalDevice>(physical_count);
857     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &returned_physical_count, physical_device_handles_1.data()));
858     ASSERT_EQ(physical_count, returned_physical_count);
859     std::vector<VkPhysicalDevice> physical_device_handles_2 = std::vector<VkPhysicalDevice>(physical_count);
860     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &returned_physical_count, physical_device_handles_2.data()));
861     ASSERT_EQ(physical_count, returned_physical_count);
862     // Make sure devices are same between the two
863     for (uint32_t count = 0; count < driver.physical_devices.size(); ++count) {
864         ASSERT_EQ(physical_device_handles_1[count], physical_device_handles_2[count]);
865     }
866 }
867 
TEST(EnumeratePhysicalDevices, CallTwiceIncompleteOnceNormal)868 TEST(EnumeratePhysicalDevices, CallTwiceIncompleteOnceNormal) {
869     FrameworkEnvironment env{};
870     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).set_min_icd_interface_version(5);
871 
872     for (size_t i = 0; i < 8; i++) {
873         driver.physical_devices.emplace_back(std::string("physical_device_") + std::to_string(i));
874     }
875 
876     InstWrapper inst{env.vulkan_functions};
877     inst.CheckCreate();
878 
879     // Query 3, then 5, then all
880     uint32_t physical_count = static_cast<uint32_t>(driver.physical_devices.size());
881     uint32_t returned_physical_count = 3;
882     std::vector<VkPhysicalDevice> physical_device_handles_1 = std::vector<VkPhysicalDevice>(returned_physical_count);
883     ASSERT_EQ(VK_INCOMPLETE, inst->vkEnumeratePhysicalDevices(inst, &returned_physical_count, physical_device_handles_1.data()));
884     ASSERT_EQ(3U, returned_physical_count);
885     returned_physical_count = 5;
886     std::vector<VkPhysicalDevice> physical_device_handles_2 = std::vector<VkPhysicalDevice>(returned_physical_count);
887     ASSERT_EQ(VK_INCOMPLETE, inst->vkEnumeratePhysicalDevices(inst, &returned_physical_count, physical_device_handles_2.data()));
888     ASSERT_EQ(5U, returned_physical_count);
889     returned_physical_count = physical_count;
890     std::vector<VkPhysicalDevice> physical_device_handles_3 = std::vector<VkPhysicalDevice>(returned_physical_count);
891     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &returned_physical_count, physical_device_handles_3.data()));
892     ASSERT_EQ(physical_count, returned_physical_count);
893     // Make sure devices are same between the three
894     for (uint32_t count = 0; count < driver.physical_devices.size(); ++count) {
895         if (count < physical_device_handles_1.size()) {
896             ASSERT_EQ(physical_device_handles_1[count], physical_device_handles_3[count]);
897         }
898         if (count < physical_device_handles_2.size()) {
899             ASSERT_EQ(physical_device_handles_2[count], physical_device_handles_3[count]);
900         }
901     }
902 }
903 
TEST(EnumeratePhysicalDevices, CallThriceSuccessReduce)904 TEST(EnumeratePhysicalDevices, CallThriceSuccessReduce) {
905     FrameworkEnvironment env{};
906     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).set_min_icd_interface_version(5);
907 
908     for (size_t i = 0; i < 8; i++) {
909         driver.physical_devices.emplace_back(std::string("physical_device_") + std::to_string(i));
910     }
911 
912     InstWrapper inst{env.vulkan_functions};
913     inst.CheckCreate();
914 
915     // Query all at first, then 5, then 3
916     uint32_t physical_count = static_cast<uint32_t>(driver.physical_devices.size());
917     uint32_t returned_physical_count = physical_count;
918     std::vector<VkPhysicalDevice> physical_device_handles_1 = std::vector<VkPhysicalDevice>(physical_count);
919     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &returned_physical_count, physical_device_handles_1.data()));
920     ASSERT_EQ(physical_count, returned_physical_count);
921     returned_physical_count = 5;
922     std::vector<VkPhysicalDevice> physical_device_handles_2 = std::vector<VkPhysicalDevice>(returned_physical_count);
923     ASSERT_EQ(VK_INCOMPLETE, inst->vkEnumeratePhysicalDevices(inst, &returned_physical_count, physical_device_handles_2.data()));
924     ASSERT_EQ(5U, returned_physical_count);
925     returned_physical_count = 3;
926     std::vector<VkPhysicalDevice> physical_device_handles_3 = std::vector<VkPhysicalDevice>(returned_physical_count);
927     ASSERT_EQ(VK_INCOMPLETE, inst->vkEnumeratePhysicalDevices(inst, &returned_physical_count, physical_device_handles_3.data()));
928     ASSERT_EQ(3U, returned_physical_count);
929     // Make sure devices are same between the three
930     for (uint32_t count = 0; count < driver.physical_devices.size(); ++count) {
931         if (count < physical_device_handles_2.size()) {
932             ASSERT_EQ(physical_device_handles_2[count], physical_device_handles_1[count]);
933         }
934         if (count < physical_device_handles_3.size()) {
935             ASSERT_EQ(physical_device_handles_3[count], physical_device_handles_1[count]);
936         }
937     }
938 }
939 
TEST(EnumeratePhysicalDevices, CallThriceAddInBetween)940 TEST(EnumeratePhysicalDevices, CallThriceAddInBetween) {
941     FrameworkEnvironment env{};
942     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).set_min_icd_interface_version(5);
943 
944     driver.physical_devices.emplace_back("physical_device_0");
945     driver.physical_devices.emplace_back("physical_device_1");
946 
947     InstWrapper inst{env.vulkan_functions};
948     inst.CheckCreate();
949 
950     uint32_t physical_count = static_cast<uint32_t>(driver.physical_devices.size());
951     uint32_t returned_physical_count = physical_count;
952     std::vector<VkPhysicalDevice> physical_device_handles_1 = std::vector<VkPhysicalDevice>(physical_count);
953     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &returned_physical_count, physical_device_handles_1.data()));
954     ASSERT_EQ(physical_count, returned_physical_count);
955 
956     driver.physical_devices.emplace_back("physical_device_2");
957     driver.physical_devices.emplace_back("physical_device_3");
958 
959     std::vector<VkPhysicalDevice> physical_device_handles_2 = std::vector<VkPhysicalDevice>(returned_physical_count);
960     ASSERT_EQ(VK_INCOMPLETE, inst->vkEnumeratePhysicalDevices(inst, &returned_physical_count, physical_device_handles_2.data()));
961     ASSERT_EQ(physical_count, returned_physical_count);
962 
963     physical_count = static_cast<uint32_t>(driver.physical_devices.size());
964     returned_physical_count = physical_count;
965     std::vector<VkPhysicalDevice> physical_device_handles_3 = std::vector<VkPhysicalDevice>(returned_physical_count);
966     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &returned_physical_count, physical_device_handles_3.data()));
967     ASSERT_EQ(physical_count, returned_physical_count);
968     // Make sure devices are same between the three
969     for (uint32_t count = 0; count < physical_device_handles_3.size(); ++count) {
970         if (count < physical_device_handles_1.size()) {
971             ASSERT_EQ(physical_device_handles_1[count], physical_device_handles_3[count]);
972         }
973         if (count < physical_device_handles_2.size()) {
974             ASSERT_EQ(physical_device_handles_2[count], physical_device_handles_3[count]);
975         }
976     }
977 }
978 
TEST(EnumeratePhysicalDevices, CallThriceRemoveInBetween)979 TEST(EnumeratePhysicalDevices, CallThriceRemoveInBetween) {
980     FrameworkEnvironment env{};
981     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).set_min_icd_interface_version(5);
982 
983     for (size_t i = 0; i < 4; i++) {
984         driver.physical_devices.emplace_back(std::string("physical_device_") + std::to_string(i));
985     }
986 
987     InstWrapper inst{env.vulkan_functions};
988     inst.CheckCreate();
989 
990     uint32_t physical_count = static_cast<uint32_t>(driver.physical_devices.size());
991     uint32_t returned_physical_count = physical_count;
992     std::vector<VkPhysicalDevice> physical_device_handles_1 = std::vector<VkPhysicalDevice>(physical_count);
993     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &returned_physical_count, physical_device_handles_1.data()));
994     ASSERT_EQ(physical_count, returned_physical_count);
995 
996     // Delete the 2nd physical device
997     driver.physical_devices.erase(std::next(driver.physical_devices.begin()));
998 
999     physical_count = static_cast<uint32_t>(driver.physical_devices.size());
1000     std::vector<VkPhysicalDevice> physical_device_handles_2 = std::vector<VkPhysicalDevice>(returned_physical_count);
1001     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &returned_physical_count, physical_device_handles_2.data()));
1002     ASSERT_EQ(physical_count, returned_physical_count);
1003     physical_device_handles_2.resize(returned_physical_count);
1004 
1005     returned_physical_count = physical_count;
1006     std::vector<VkPhysicalDevice> physical_device_handles_3 = std::vector<VkPhysicalDevice>(returned_physical_count);
1007     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &returned_physical_count, physical_device_handles_3.data()));
1008     ASSERT_EQ(physical_count, returned_physical_count);
1009 
1010     // Make sure one has 1 more device that two or three
1011     ASSERT_EQ(physical_device_handles_1.size(), physical_device_handles_2.size() + 1);
1012     ASSERT_EQ(physical_device_handles_1.size(), physical_device_handles_3.size() + 1);
1013 
1014     // Make sure the devices in two and three are all found in one
1015     uint32_t two_found = 0;
1016     uint32_t three_found = 0;
1017     for (uint32_t count = 0; count < physical_device_handles_1.size(); ++count) {
1018         for (uint32_t int_count = 0; int_count < physical_device_handles_2.size(); ++int_count) {
1019             if (physical_device_handles_2[int_count] == physical_device_handles_1[count]) {
1020                 two_found++;
1021                 break;
1022             }
1023         }
1024         for (uint32_t int_count = 0; int_count < physical_device_handles_3.size(); ++int_count) {
1025             if (physical_device_handles_3[int_count] == physical_device_handles_1[count]) {
1026                 three_found++;
1027                 break;
1028             }
1029         }
1030     }
1031     ASSERT_EQ(two_found, returned_physical_count);
1032     ASSERT_EQ(three_found, returned_physical_count);
1033 }
1034 
TEST(EnumeratePhysicalDevices, MultipleAddRemoves)1035 TEST(EnumeratePhysicalDevices, MultipleAddRemoves) {
1036     FrameworkEnvironment env{};
1037     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).set_min_icd_interface_version(5);
1038 
1039     for (size_t i = 0; i < 4; i++) {
1040         driver.physical_devices.emplace_back(std::string("physical_device_") + std::to_string(i));
1041     }
1042     std::array<std::vector<VkPhysicalDevice>, 8> physical_dev_handles;
1043 
1044     InstWrapper inst{env.vulkan_functions};
1045     inst.CheckCreate();
1046 
1047     uint32_t physical_count = static_cast<uint32_t>(driver.physical_devices.size());
1048     uint32_t returned_physical_count = physical_count;
1049     physical_dev_handles[0].resize(physical_count);
1050     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &returned_physical_count, physical_dev_handles[0].data()));
1051     ASSERT_EQ(physical_count, returned_physical_count);
1052 
1053     // Delete the 2nd physical device (0, 2, 3)
1054     driver.physical_devices.erase(std::next(driver.physical_devices.begin()));
1055 
1056     // Query using old number from last call (4), but it should only return 3
1057     physical_count = static_cast<uint32_t>(driver.physical_devices.size());
1058     physical_dev_handles[1].resize(returned_physical_count);
1059     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &returned_physical_count, physical_dev_handles[1].data()));
1060     ASSERT_EQ(physical_count, returned_physical_count);
1061     physical_dev_handles[1].resize(returned_physical_count);
1062 
1063     // Add two new physical devices to the front (A, B, 0, 2, 3)
1064     driver.physical_devices.emplace(driver.physical_devices.begin(), "physical_device_B");
1065     driver.physical_devices.emplace(driver.physical_devices.begin(), "physical_device_A");
1066 
1067     // Query using old number from last call (3), but it should be 5
1068     physical_count = static_cast<uint32_t>(driver.physical_devices.size());
1069     physical_dev_handles[2].resize(returned_physical_count);
1070     ASSERT_EQ(VK_INCOMPLETE, inst->vkEnumeratePhysicalDevices(inst, &returned_physical_count, physical_dev_handles[2].data()));
1071     ASSERT_EQ(physical_count - 2, returned_physical_count);
1072     physical_dev_handles[2].resize(returned_physical_count);
1073 
1074     // Query again to get all 5
1075     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &returned_physical_count, nullptr));
1076     physical_dev_handles[3].resize(returned_physical_count);
1077     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &returned_physical_count, physical_dev_handles[3].data()));
1078     ASSERT_EQ(physical_count, returned_physical_count);
1079 
1080     // Delete last two physical devices (A, B, 0, 2)
1081     driver.physical_devices.pop_back();
1082 
1083     // Query using old number from last call (5), but it should be 4
1084     physical_count = static_cast<uint32_t>(driver.physical_devices.size());
1085     physical_dev_handles[4].resize(returned_physical_count);
1086     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &returned_physical_count, physical_dev_handles[4].data()));
1087     ASSERT_EQ(physical_count, returned_physical_count);
1088     physical_dev_handles[4].resize(returned_physical_count);
1089     // Adjust size and query again, should be the same
1090     physical_dev_handles[5].resize(returned_physical_count);
1091     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &returned_physical_count, physical_dev_handles[5].data()));
1092 
1093     // Insert a new physical device (A, B, C, 0, 2)
1094     driver.physical_devices.insert(driver.physical_devices.begin() + 2, "physical_device_C");
1095 
1096     // Query using old number from last call (4), but it should be 5
1097     physical_count = static_cast<uint32_t>(driver.physical_devices.size());
1098     physical_dev_handles[6].resize(returned_physical_count);
1099     ASSERT_EQ(VK_INCOMPLETE, inst->vkEnumeratePhysicalDevices(inst, &returned_physical_count, physical_dev_handles[6].data()));
1100     ASSERT_EQ(physical_count - 1, returned_physical_count);
1101     // Query again to get all 5
1102     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &returned_physical_count, nullptr));
1103     physical_dev_handles[7].resize(returned_physical_count);
1104     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &returned_physical_count, physical_dev_handles[7].data()));
1105 
1106     // Check final results
1107     // One   [4] - 0, 1, 2, 3
1108     // Two   [3] - 0, 2, 3
1109     // Three [3] - A, B, 0
1110     // Four  [5] - A, B, 0, 2, 3
1111     // Five  [4] - A, B, 0, 2
1112     // Six   [4] - A, B, 0, 2
1113     // Seven [4] - A, B, C, 0
1114     // Eight [5] - A, B, C, 0, 2
1115     ASSERT_EQ(4U, physical_dev_handles[0].size());
1116     ASSERT_EQ(3U, physical_dev_handles[1].size());
1117     ASSERT_EQ(3U, physical_dev_handles[2].size());
1118     ASSERT_EQ(5U, physical_dev_handles[3].size());
1119     ASSERT_EQ(4U, physical_dev_handles[4].size());
1120     ASSERT_EQ(4U, physical_dev_handles[5].size());
1121     ASSERT_EQ(4U, physical_dev_handles[6].size());
1122     ASSERT_EQ(5U, physical_dev_handles[7].size());
1123 
1124     // Make sure the devices in two and three are all found in one
1125     uint32_t found_items[8]{};
1126     for (uint32_t handle = 1; handle < 8; ++handle) {
1127         for (uint32_t count = 0; count < physical_dev_handles[0].size(); ++count) {
1128             for (uint32_t int_count = 0; int_count < physical_dev_handles[handle].size(); ++int_count) {
1129                 if (physical_dev_handles[handle][int_count] == physical_dev_handles[0][count]) {
1130                     found_items[handle]++;
1131                     break;
1132                 }
1133             }
1134         }
1135     }
1136     // Items matching from first call (must be >= since handle re-use does occur)
1137     ASSERT_EQ(found_items[1], 3U);
1138     ASSERT_GE(found_items[2], 1U);
1139     ASSERT_GE(found_items[3], 3U);
1140     ASSERT_GE(found_items[4], 2U);
1141     ASSERT_GE(found_items[5], 2U);
1142     ASSERT_GE(found_items[6], 1U);
1143     ASSERT_GE(found_items[7], 2U);
1144 
1145     memset(found_items, 0, 8 * sizeof(uint32_t));
1146     for (uint32_t handle = 0; handle < 7; ++handle) {
1147         for (uint32_t count = 0; count < physical_dev_handles[7].size(); ++count) {
1148             for (uint32_t int_count = 0; int_count < physical_dev_handles[handle].size(); ++int_count) {
1149                 if (physical_dev_handles[handle][int_count] == physical_dev_handles[7][count]) {
1150                     found_items[handle]++;
1151                     break;
1152                 }
1153             }
1154         }
1155     }
1156     // Items matching from last call (must be >= since handle re-use does occur)
1157     ASSERT_GE(found_items[0], 2U);
1158     ASSERT_GE(found_items[1], 2U);
1159     ASSERT_GE(found_items[2], 3U);
1160     ASSERT_GE(found_items[3], 4U);
1161     ASSERT_GE(found_items[4], 4U);
1162     ASSERT_GE(found_items[5], 4U);
1163     ASSERT_GE(found_items[6], 4U);
1164 }
1165 
TEST(CreateDevice, ExtensionNotPresent)1166 TEST(CreateDevice, ExtensionNotPresent) {
1167     FrameworkEnvironment env{};
1168     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device("physical_device_0");
1169 
1170     InstWrapper inst{env.vulkan_functions};
1171     inst.CheckCreate();
1172 
1173     VkPhysicalDevice phys_dev = inst.GetPhysDev();
1174 
1175     DeviceWrapper dev{inst};
1176     dev.create_info.add_extension("NotPresent");
1177 
1178     dev.CheckCreate(phys_dev, VK_ERROR_EXTENSION_NOT_PRESENT);
1179 }
1180 
1181 // LX535 / MI-76: Device layers are deprecated.
1182 // Ensure that no errors occur if a bogus device layer list is passed to vkCreateDevice.
1183 // https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#extendingvulkan-layers-devicelayerdeprecation
TEST(CreateDevice, LayersNotPresent)1184 TEST(CreateDevice, LayersNotPresent) {
1185     FrameworkEnvironment env{};
1186     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device("physical_device_0");
1187 
1188     InstWrapper inst{env.vulkan_functions};
1189     inst.CheckCreate();
1190 
1191     VkPhysicalDevice phys_dev = inst.GetPhysDev();
1192 
1193     DeviceWrapper dev{inst};
1194     dev.create_info.add_layer("NotPresent");
1195 
1196     dev.CheckCreate(phys_dev);
1197 }
1198 
1199 // Device layers are deprecated.
1200 // Ensure that no error occur if instance and device are created with the same list of layers.
1201 // https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#extendingvulkan-layers-devicelayerdeprecation
TEST(CreateDevice, MatchInstanceAndDeviceLayers)1202 TEST(CreateDevice, MatchInstanceAndDeviceLayers) {
1203     FrameworkEnvironment env{};
1204     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device("physical_device_0");
1205 
1206     const char* layer_name = "TestLayer";
1207     env.add_explicit_layer(
1208         ManifestLayer{}.add_layer(
1209             ManifestLayer::LayerDescription{}.set_name(layer_name).set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)),
1210         "test_layer.json");
1211 
1212     InstWrapper inst{env.vulkan_functions};
1213     inst.create_info.add_layer(layer_name);
1214     inst.CheckCreate();
1215 
1216     VkPhysicalDevice phys_dev = inst.GetPhysDev();
1217 
1218     DeviceWrapper dev{inst};
1219     dev.create_info.add_layer(layer_name);
1220 
1221     dev.CheckCreate(phys_dev);
1222 }
1223 
1224 // Device layers are deprecated.
1225 // Ensure that a message is generated when instance and device are created with different list of layers.
1226 // At best , the user can list only instance layers in the device layer list
1227 // https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#extendingvulkan-layers-devicelayerdeprecation
TEST(CreateDevice, UnmatchInstanceAndDeviceLayers)1228 TEST(CreateDevice, UnmatchInstanceAndDeviceLayers) {
1229     FrameworkEnvironment env{};
1230     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device("physical_device_0");
1231 
1232     const char* layer_name = "TestLayer";
1233     env.add_explicit_layer(
1234         ManifestLayer{}.add_layer(
1235             ManifestLayer::LayerDescription{}.set_name(layer_name).set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)),
1236         "test_layer.json");
1237 
1238     DebugUtilsLogger debug_log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT};
1239     InstWrapper inst{env.vulkan_functions};
1240     FillDebugUtilsCreateDetails(inst.create_info, debug_log);
1241     inst.CheckCreate();
1242 
1243     DebugUtilsWrapper log{inst, VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT};
1244     CreateDebugUtilsMessenger(log);
1245 
1246     VkPhysicalDevice phys_dev = inst.GetPhysDev();
1247 
1248     DeviceWrapper dev{inst};
1249     dev.create_info.add_layer(layer_name);
1250 
1251     dev.CheckCreate(phys_dev);
1252 
1253     ASSERT_TRUE(
1254         log.find("loader_create_device_chain: Using deprecated and ignored 'ppEnabledLayerNames' member of 'VkDeviceCreateInfo' "
1255                  "when creating a Vulkan device."));
1256 }
1257 
1258 // Device layers are deprecated.
1259 // Ensure that when VkInstanceCreateInfo is deleted, the check of the instance layer lists is running correctly during VkDevice
1260 // creation
1261 // https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#extendingvulkan-layers-devicelayerdeprecation
TEST(CreateDevice, CheckCopyOfInstanceLayerNames)1262 TEST(CreateDevice, CheckCopyOfInstanceLayerNames) {
1263     FrameworkEnvironment env{};
1264     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device("physical_device_0");
1265 
1266     const char* layer_name = "TestLayer";
1267     env.add_explicit_layer(
1268         ManifestLayer{}.add_layer(
1269             ManifestLayer::LayerDescription{}.set_name(layer_name).set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)),
1270         "test_layer.json");
1271 
1272     InstWrapper inst{env.vulkan_functions};
1273     {
1274         // We intentionally create a local InstanceCreateInfo that goes out of scope at the } so that when dev.CheckCreate is called
1275         // the layer name pointers are no longer valid
1276         InstanceCreateInfo create_info{};
1277         create_info.add_layer(layer_name);
1278         inst.CheckCreateWithInfo(create_info);
1279     }
1280 
1281     VkPhysicalDevice phys_dev = inst.GetPhysDev();
1282 
1283     DeviceWrapper dev{inst};
1284     dev.create_info.add_layer(layer_name);
1285 
1286     dev.CheckCreate(phys_dev);
1287 }
1288 
TEST(CreateDevice, ConsecutiveCreate)1289 TEST(CreateDevice, ConsecutiveCreate) {
1290     FrameworkEnvironment env{};
1291     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
1292 
1293     for (uint32_t i = 0; i < 100; i++) {
1294         driver.physical_devices.emplace_back("physical_device_0");
1295     }
1296     InstWrapper inst{env.vulkan_functions};
1297     inst.CheckCreate();
1298 
1299     auto phys_devs = inst.GetPhysDevs(100);
1300     for (uint32_t i = 0; i < 100; i++) {
1301         DeviceWrapper dev{inst};
1302         dev.CheckCreate(phys_devs[i]);
1303     }
1304 }
1305 
TEST(CreateDevice, ConsecutiveCreateWithoutDestruction)1306 TEST(CreateDevice, ConsecutiveCreateWithoutDestruction) {
1307     FrameworkEnvironment env{};
1308     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
1309 
1310     for (uint32_t i = 0; i < 100; i++) {
1311         driver.physical_devices.emplace_back("physical_device_0");
1312     }
1313     InstWrapper inst{env.vulkan_functions};
1314     inst.CheckCreate();
1315 
1316     auto phys_devs = inst.GetPhysDevs(100);
1317 
1318     std::vector<DeviceWrapper> devices;
1319     for (uint32_t i = 0; i < 100; i++) {
1320         devices.emplace_back(inst);
1321         DeviceWrapper& dev = devices.back();
1322 
1323         dev.CheckCreate(phys_devs[i]);
1324     }
1325 }
1326 
TEST(TryLoadWrongBinaries, WrongICD)1327 TEST(TryLoadWrongBinaries, WrongICD) {
1328     FrameworkEnvironment env{};
1329     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device("physical_device_0");
1330     env.add_icd(TestICDDetails(CURRENT_PLATFORM_DUMMY_BINARY_WRONG_TYPE).set_is_fake(true));
1331 
1332     DebugUtilsLogger log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
1333     InstWrapper inst{env.vulkan_functions};
1334     FillDebugUtilsCreateDetails(inst.create_info, log);
1335     inst.CheckCreate();
1336 
1337 #if _WIN32 || _WIN64
1338     ASSERT_TRUE(log.find("Failed to open dynamic library"));
1339 #endif
1340 #if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__GNU__)
1341 #if defined(__x86_64__)
1342     ASSERT_TRUE(log.find("wrong ELF class: ELFCLASS32"));
1343 #else
1344     ASSERT_TRUE(log.find("wrong ELF class: ELFCLASS64"));
1345 #endif
1346 #endif
1347 
1348     uint32_t driver_count = 0;
1349     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &driver_count, nullptr));
1350     ASSERT_EQ(driver_count, 1U);
1351 }
1352 
TEST(TryLoadWrongBinaries, WrongExplicit)1353 TEST(TryLoadWrongBinaries, WrongExplicit) {
1354     FrameworkEnvironment env{};
1355     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device("physical_device_0");
1356 
1357     const char* layer_name = "DummyLayerExplicit";
1358     env.add_fake_explicit_layer(
1359         ManifestLayer{}.add_layer(
1360             ManifestLayer::LayerDescription{}.set_name(layer_name).set_lib_path(CURRENT_PLATFORM_DUMMY_BINARY_WRONG_TYPE)),
1361         "dummy_test_layer.json");
1362 
1363     auto layer_props = env.GetLayerProperties(1);
1364     ASSERT_TRUE(string_eq(layer_name, layer_props[0].layerName));
1365 
1366     DebugUtilsLogger log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
1367     InstWrapper inst{env.vulkan_functions};
1368     inst.create_info.add_layer(layer_name);
1369     FillDebugUtilsCreateDetails(inst.create_info, log);
1370 
1371     // Explicit layer not found should generate a VK_ERROR_LAYER_NOT_PRESENT error message.
1372     inst.CheckCreate(VK_ERROR_LAYER_NOT_PRESENT);
1373 
1374     // Should get an error message for the explicit layer
1375 #if !defined(__APPLE__)
1376     ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name) + std::string("\" was wrong bit-type!")));
1377 #else   // __APPLE__
1378     // Apple only throws a wrong library type of error
1379     ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name) + std::string("\" failed to load!")));
1380 #endif  // __APPLE__
1381 }
1382 
TEST(TryLoadWrongBinaries, WrongImplicit)1383 TEST(TryLoadWrongBinaries, WrongImplicit) {
1384     FrameworkEnvironment env{};
1385     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device("physical_device_0");
1386 
1387     const char* layer_name = "DummyLayerImplicit0";
1388     env.add_fake_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
1389                                                               .set_name(layer_name)
1390                                                               .set_lib_path(CURRENT_PLATFORM_DUMMY_BINARY_WRONG_TYPE)
1391                                                               .set_disable_environment("DISABLE_ENV")),
1392                                 "dummy_test_layer.json");
1393 
1394     auto layer_props = env.GetLayerProperties(1);
1395     ASSERT_TRUE(string_eq(layer_name, layer_props[0].layerName));
1396 
1397     DebugUtilsLogger log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
1398     InstWrapper inst{env.vulkan_functions};
1399     FillDebugUtilsCreateDetails(inst.create_info, log);
1400 
1401     // We don't want to return VK_ERROR_LAYER_NOT_PRESENT for missing implicit layers because it's not the
1402     // application asking for them.
1403     inst.CheckCreate(VK_SUCCESS);
1404 
1405 #if !defined(__APPLE__)
1406     // Should get an info message for the bad implicit layer
1407     ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name) + std::string("\" was wrong bit-type.")));
1408 #else   // __APPLE__
1409     // Apple only throws a wrong library type of error
1410     ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name) + std::string("\" failed to load.")));
1411 #endif  // __APPLE__
1412 }
1413 
TEST(TryLoadWrongBinaries, WrongExplicitAndImplicit)1414 TEST(TryLoadWrongBinaries, WrongExplicitAndImplicit) {
1415     FrameworkEnvironment env{};
1416     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device("physical_device_0");
1417 
1418     const char* layer_name_0 = "DummyLayerExplicit";
1419     env.add_fake_explicit_layer(
1420         ManifestLayer{}.add_layer(
1421             ManifestLayer::LayerDescription{}.set_name(layer_name_0).set_lib_path(CURRENT_PLATFORM_DUMMY_BINARY_WRONG_TYPE)),
1422         "dummy_test_layer_0.json");
1423     const char* layer_name_1 = "DummyLayerImplicit";
1424     env.add_fake_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
1425                                                               .set_name(layer_name_1)
1426                                                               .set_lib_path(CURRENT_PLATFORM_DUMMY_BINARY_WRONG_TYPE)
1427                                                               .set_disable_environment("DISABLE_ENV")),
1428                                 "dummy_test_layer_1.json");
1429 
1430     auto layer_props = env.GetLayerProperties(2);
1431     ASSERT_TRUE(check_permutation({layer_name_0, layer_name_1}, layer_props));
1432 
1433     DebugUtilsLogger log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
1434     InstWrapper inst{env.vulkan_functions};
1435     inst.create_info.add_layer(layer_name_0);
1436     FillDebugUtilsCreateDetails(inst.create_info, log);
1437 
1438     // Explicit layer not found should generate a VK_ERROR_LAYER_NOT_PRESENT error message.
1439     inst.CheckCreate(VK_ERROR_LAYER_NOT_PRESENT);
1440 
1441 #if !defined(__APPLE__)
1442     // Should get error messages for both (the explicit is second and we don't want the implicit to return before the explicit
1443     // triggers a failure during vkCreateInstance)
1444     ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name_0) + std::string("\" was wrong bit-type!")));
1445     ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name_1) + std::string("\" was wrong bit-type.")));
1446 #else   // __APPLE__
1447     // Apple only throws a wrong library type of error
1448     ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name_0) + std::string("\" failed to load!")));
1449     ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name_1) + std::string("\" failed to load.")));
1450 #endif  // __APPLE__
1451 }
1452 
TEST(TryLoadWrongBinaries, WrongExplicitAndImplicitErrorOnly)1453 TEST(TryLoadWrongBinaries, WrongExplicitAndImplicitErrorOnly) {
1454     FrameworkEnvironment env{};
1455     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device("physical_device_0");
1456 
1457     const char* layer_name_0 = "DummyLayerExplicit";
1458     env.add_fake_explicit_layer(
1459         ManifestLayer{}.add_layer(
1460             ManifestLayer::LayerDescription{}.set_name(layer_name_0).set_lib_path(CURRENT_PLATFORM_DUMMY_BINARY_WRONG_TYPE)),
1461         "dummy_test_layer_0.json");
1462     const char* layer_name_1 = "DummyLayerImplicit";
1463     env.add_fake_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
1464                                                               .set_name(layer_name_1)
1465                                                               .set_lib_path(CURRENT_PLATFORM_DUMMY_BINARY_WRONG_TYPE)
1466                                                               .set_disable_environment("DISABLE_ENV")),
1467                                 "dummy_test_layer_1.json");
1468 
1469     auto layer_props = env.GetLayerProperties(2);
1470     ASSERT_TRUE(check_permutation({layer_name_0, layer_name_1}, layer_props));
1471 
1472     DebugUtilsLogger log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
1473     InstWrapper inst{env.vulkan_functions};
1474     inst.create_info.add_layer(layer_name_0);
1475     FillDebugUtilsCreateDetails(inst.create_info, log);
1476 
1477     // Explicit layer not found should generate a VK_ERROR_LAYER_NOT_PRESENT error message.
1478     inst.CheckCreate(VK_ERROR_LAYER_NOT_PRESENT);
1479 
1480 #if !defined(__APPLE__)
1481     // Should not get an error messages for either
1482     ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name_0) + std::string("\" was wrong bit-type!")));
1483     ASSERT_FALSE(log.find(std::string("Requested layer \"") + std::string(layer_name_1) + std::string("\" was wrong bit-type.")));
1484 #else   // __APPLE__
1485     // Apple only throws a wrong library type of error
1486     ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name_0) + std::string("\" failed to load!")));
1487     ASSERT_FALSE(log.find(std::string("Requested layer \"") + std::string(layer_name_1) + std::string("\" failed to load.")));
1488 #endif  // __APPLE__
1489 }
1490 
TEST(TryLoadWrongBinaries, BadExplicit)1491 TEST(TryLoadWrongBinaries, BadExplicit) {
1492     FrameworkEnvironment env{};
1493     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device("physical_device_0");
1494 
1495     const char* layer_name = "DummyLayerExplicit";
1496     env.add_fake_explicit_layer(
1497         ManifestLayer{}.add_layer(
1498             ManifestLayer::LayerDescription{}.set_name(layer_name).set_lib_path(CURRENT_PLATFORM_DUMMY_BINARY_BAD)),
1499         "dummy_test_layer.json");
1500 
1501     auto layer_props = env.GetLayerProperties(1);
1502     ASSERT_TRUE(string_eq(layer_name, layer_props[0].layerName));
1503 
1504     DebugUtilsLogger log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
1505     InstWrapper inst{env.vulkan_functions};
1506     inst.create_info.add_layer(layer_name);
1507     FillDebugUtilsCreateDetails(inst.create_info, log);
1508 
1509     // Explicit layer not found should generate a VK_ERROR_LAYER_NOT_PRESENT error message.
1510     inst.CheckCreate(VK_ERROR_LAYER_NOT_PRESENT);
1511 
1512     // Should get an error message for the bad explicit
1513     ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name) + std::string("\" failed to load!")));
1514 }
1515 
TEST(TryLoadWrongBinaries, BadImplicit)1516 TEST(TryLoadWrongBinaries, BadImplicit) {
1517     FrameworkEnvironment env{};
1518     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device("physical_device_0");
1519 
1520     const char* layer_name = "DummyLayerImplicit0";
1521     env.add_fake_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
1522                                                               .set_name(layer_name)
1523                                                               .set_lib_path(CURRENT_PLATFORM_DUMMY_BINARY_BAD)
1524                                                               .set_disable_environment("DISABLE_ENV")),
1525                                 "dummy_test_layer.json");
1526 
1527     auto layer_props = env.GetLayerProperties(1);
1528     ASSERT_TRUE(string_eq(layer_name, layer_props[0].layerName));
1529 
1530     DebugUtilsLogger log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
1531     InstWrapper inst{env.vulkan_functions};
1532     FillDebugUtilsCreateDetails(inst.create_info, log);
1533 
1534     // We don't want to return VK_ERROR_LAYER_NOT_PRESENT for missing implicit layers because it's not the
1535     // application asking for them.
1536     inst.CheckCreate(VK_SUCCESS);
1537 
1538     // Should get an info message for the bad implicit
1539     ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name) + std::string("\" failed to load.")));
1540 }
1541 
TEST(TryLoadWrongBinaries, BadExplicitAndImplicit)1542 TEST(TryLoadWrongBinaries, BadExplicitAndImplicit) {
1543     FrameworkEnvironment env{};
1544     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device("physical_device_0");
1545 
1546     const char* layer_name_0 = "DummyLayerExplicit";
1547     env.add_fake_explicit_layer(
1548         ManifestLayer{}.add_layer(
1549             ManifestLayer::LayerDescription{}.set_name(layer_name_0).set_lib_path(CURRENT_PLATFORM_DUMMY_BINARY_BAD)),
1550         "dummy_test_layer_0.json");
1551     const char* layer_name_1 = "DummyLayerImplicit0";
1552     env.add_fake_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
1553                                                               .set_name(layer_name_1)
1554                                                               .set_lib_path(CURRENT_PLATFORM_DUMMY_BINARY_BAD)
1555                                                               .set_disable_environment("DISABLE_ENV")),
1556                                 "dummy_test_layer_1.json");
1557 
1558     auto layer_props = env.GetLayerProperties(2);
1559     ASSERT_TRUE(check_permutation({layer_name_0, layer_name_1}, layer_props));
1560 
1561     DebugUtilsLogger log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
1562     InstWrapper inst{env.vulkan_functions};
1563     inst.create_info.add_layer(layer_name_0);
1564     FillDebugUtilsCreateDetails(inst.create_info, log);
1565 
1566     // Explicit layer not found should generate a VK_ERROR_LAYER_NOT_PRESENT error message.
1567     inst.CheckCreate(VK_ERROR_LAYER_NOT_PRESENT);
1568 
1569     // Apple only throws a wrong library type of error
1570     ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name_0) + std::string("\" failed to load!")));
1571     ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name_1) + std::string("\" failed to load.")));
1572 }
1573 
TEST(TryLoadWrongBinaries, WrongArchDriver)1574 TEST(TryLoadWrongBinaries, WrongArchDriver) {
1575     FrameworkEnvironment env{};
1576     // Intentionally set the wrong arch
1577     env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_2}.icd_manifest.set_library_arch(sizeof(void*) == 4 ? "64" : "32"))
1578         .add_physical_device("physical_device_0");
1579 
1580     DebugUtilsLogger log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
1581     InstWrapper inst{env.vulkan_functions};
1582     FillDebugUtilsCreateDetails(inst.create_info, log);
1583     inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER);
1584     ASSERT_TRUE(
1585         log.find("loader_parse_icd_manifest: Driver library architecture doesn't match the current running architecture, skipping "
1586                  "this driver"));
1587 }
1588 
TEST(TryLoadWrongBinaries, WrongArchLayer)1589 TEST(TryLoadWrongBinaries, WrongArchLayer) {
1590     FrameworkEnvironment env{};
1591     env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_2}).add_physical_device("physical_device_0");
1592 
1593     const char* layer_name = "TestLayer";
1594     env.add_explicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
1595                                                          .set_name(layer_name)
1596                                                          .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
1597                                                          // Intentionally set the wrong arch
1598                                                          .set_library_arch(sizeof(void*) == 4 ? "64" : "32")),
1599                            "test_layer.json");
1600 
1601     DebugUtilsLogger log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
1602     InstWrapper inst{env.vulkan_functions};
1603     FillDebugUtilsCreateDetails(inst.create_info, log);
1604     inst.create_info.add_layer(layer_name);
1605     inst.CheckCreate(VK_ERROR_LAYER_NOT_PRESENT);
1606     ASSERT_TRUE(log.find("Layer library architecture doesn't match the current running architecture, skipping this layer"));
1607 }
1608 
TEST(EnumeratePhysicalDeviceGroups, OneCall)1609 TEST(EnumeratePhysicalDeviceGroups, OneCall) {
1610     FrameworkEnvironment env{};
1611     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1))
1612                        .set_min_icd_interface_version(5)
1613                        .set_icd_api_version(VK_API_VERSION_1_1)
1614                        .add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
1615 
1616     // ICD contains 3 devices in two groups
1617     for (size_t i = 0; i < 3; i++) {
1618         driver.physical_devices.emplace_back(std::string("physical_device_") + std::to_string(i));
1619         driver.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
1620         driver.physical_devices.back().properties.apiVersion = VK_API_VERSION_1_1;
1621     }
1622     driver.physical_device_groups.emplace_back(driver.physical_devices[0]);
1623     driver.physical_device_groups.back().use_physical_device(driver.physical_devices[1]);
1624     driver.physical_device_groups.emplace_back(driver.physical_devices[2]);
1625     const uint32_t max_physical_device_count = 3;
1626 
1627     // Core function
1628     {
1629         InstWrapper inst{env.vulkan_functions};
1630         inst.create_info.set_api_version(VK_API_VERSION_1_1);
1631         inst.CheckCreate();
1632 
1633         auto physical_devices = std::vector<VkPhysicalDevice>(max_physical_device_count);
1634         uint32_t returned_phys_dev_count = max_physical_device_count;
1635         ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &returned_phys_dev_count, physical_devices.data()));
1636         handle_assert_has_values(physical_devices);
1637 
1638         uint32_t group_count = static_cast<uint32_t>(driver.physical_device_groups.size());
1639         uint32_t returned_group_count = group_count;
1640         std::vector<VkPhysicalDeviceGroupProperties> group_props{};
1641         group_props.resize(group_count, VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
1642         ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props.data()));
1643         ASSERT_EQ(group_count, returned_group_count);
1644 
1645         // Make sure each physical device shows up in a group, but only once
1646         std::array<bool, max_physical_device_count> found{false};
1647         for (uint32_t group = 0; group < group_count; ++group) {
1648             for (uint32_t g_dev = 0; g_dev < group_props[group].physicalDeviceCount; ++g_dev) {
1649                 for (uint32_t dev = 0; dev < max_physical_device_count; ++dev) {
1650                     if (physical_devices[dev] == group_props[group].physicalDevices[g_dev]) {
1651                         ASSERT_EQ(false, found[dev]);
1652                         found[dev] = true;
1653                         break;
1654                     }
1655                 }
1656             }
1657         }
1658         for (uint32_t dev = 0; dev < max_physical_device_count; ++dev) {
1659             ASSERT_EQ(true, found[dev]);
1660         }
1661         for (auto& group : group_props) {
1662             VkDeviceGroupDeviceCreateInfo group_info{};
1663             group_info.sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO;
1664             group_info.physicalDeviceCount = group.physicalDeviceCount;
1665             group_info.pPhysicalDevices = &group.physicalDevices[0];
1666             VkBaseInStructure spacer_structure{};
1667             spacer_structure.sType = static_cast<VkStructureType>(100000);
1668             spacer_structure.pNext = reinterpret_cast<const VkBaseInStructure*>(&group_info);
1669             DeviceWrapper dev{inst};
1670             dev.create_info.dev.pNext = &spacer_structure;
1671             dev.CheckCreate(group.physicalDevices[0]);
1672 
1673             // This convoluted logic makes sure that the pNext chain is unmolested after being passed into vkCreateDevice
1674             // While not expected for applications to iterate over this chain, since it is const it is important to make sure
1675             // that the chain didn't change somehow, and especially so that iterating it doesn't crash.
1676             int count = 0;
1677             const VkBaseInStructure* pNext = reinterpret_cast<const VkBaseInStructure*>(dev.create_info.dev.pNext);
1678             while (pNext != nullptr) {
1679                 if (pNext->sType == VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO) {
1680                     ASSERT_EQ(&group_info, reinterpret_cast<const VkDeviceGroupDeviceCreateInfo*>(pNext));
1681                 }
1682                 if (pNext->sType == 100000) {
1683                     ASSERT_EQ(&spacer_structure, pNext);
1684                 }
1685                 pNext = pNext->pNext;
1686                 count++;
1687             }
1688             ASSERT_EQ(count, 2);
1689         }
1690     }
1691     driver.add_instance_extension({VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME});
1692     // Extension
1693     {
1694         InstWrapper inst{env.vulkan_functions};
1695         inst.create_info.add_extension(VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME);
1696         inst.CheckCreate();
1697 
1698         PFN_vkEnumeratePhysicalDeviceGroupsKHR vkEnumeratePhysicalDeviceGroupsKHR = inst.load("vkEnumeratePhysicalDeviceGroupsKHR");
1699 
1700         auto physical_devices = std::vector<VkPhysicalDevice>(max_physical_device_count);
1701         uint32_t returned_phys_dev_count = max_physical_device_count;
1702         ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &returned_phys_dev_count, physical_devices.data()));
1703         handle_assert_has_values(physical_devices);
1704 
1705         uint32_t group_count = static_cast<uint32_t>(driver.physical_device_groups.size());
1706         uint32_t returned_group_count = group_count;
1707         std::vector<VkPhysicalDeviceGroupProperties> group_props{};
1708         group_props.resize(group_count, VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
1709         ASSERT_EQ(VK_SUCCESS, vkEnumeratePhysicalDeviceGroupsKHR(inst, &returned_group_count, group_props.data()));
1710         ASSERT_EQ(group_count, returned_group_count);
1711 
1712         // Make sure each physical device shows up in a group, but only once
1713         std::array<bool, max_physical_device_count> found{false};
1714         for (uint32_t group = 0; group < group_count; ++group) {
1715             for (uint32_t g_dev = 0; g_dev < group_props[group].physicalDeviceCount; ++g_dev) {
1716                 for (uint32_t dev = 0; dev < max_physical_device_count; ++dev) {
1717                     if (physical_devices[dev] == group_props[group].physicalDevices[g_dev]) {
1718                         ASSERT_EQ(false, found[dev]);
1719                         found[dev] = true;
1720                         break;
1721                     }
1722                 }
1723             }
1724         }
1725         for (uint32_t dev = 0; dev < max_physical_device_count; ++dev) {
1726             ASSERT_EQ(true, found[dev]);
1727         }
1728         for (auto& group : group_props) {
1729             VkDeviceGroupDeviceCreateInfo group_info{};
1730             group_info.sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO;
1731             group_info.physicalDeviceCount = group.physicalDeviceCount;
1732             group_info.pPhysicalDevices = &group.physicalDevices[0];
1733             VkBaseInStructure spacer_structure{};
1734             spacer_structure.sType = static_cast<VkStructureType>(100000);
1735             spacer_structure.pNext = reinterpret_cast<const VkBaseInStructure*>(&group_info);
1736             DeviceWrapper dev{inst};
1737             dev.create_info.dev.pNext = &spacer_structure;
1738             dev.CheckCreate(group.physicalDevices[0]);
1739         }
1740     }
1741 }
1742 
TEST(EnumeratePhysicalDeviceGroups, TwoCall)1743 TEST(EnumeratePhysicalDeviceGroups, TwoCall) {
1744     FrameworkEnvironment env{};
1745     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1))
1746                        .set_min_icd_interface_version(5)
1747                        .set_icd_api_version(VK_API_VERSION_1_1)
1748                        .add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
1749 
1750     // ICD contains 3 devices in two groups
1751     for (size_t i = 0; i < 3; i++) {
1752         driver.physical_devices.emplace_back(std::string("physical_device_") + std::to_string(i));
1753         driver.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
1754         driver.physical_devices.back().properties.apiVersion = VK_API_VERSION_1_1;
1755     }
1756     driver.physical_device_groups.emplace_back(driver.physical_devices[0]);
1757     driver.physical_device_groups.back().use_physical_device(driver.physical_devices[1]);
1758     driver.physical_device_groups.emplace_back(driver.physical_devices[2]);
1759     const uint32_t max_physical_device_count = 3;
1760 
1761     // Core function
1762     {
1763         InstWrapper inst{env.vulkan_functions};
1764         inst.create_info.set_api_version(VK_API_VERSION_1_1);
1765         inst.CheckCreate();
1766 
1767         auto physical_devices = std::vector<VkPhysicalDevice>(max_physical_device_count);
1768         uint32_t returned_phys_dev_count = max_physical_device_count;
1769         ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &returned_phys_dev_count, physical_devices.data()));
1770         handle_assert_has_values(physical_devices);
1771 
1772         uint32_t group_count = static_cast<uint32_t>(driver.physical_device_groups.size());
1773         uint32_t returned_group_count = 0;
1774         ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, nullptr));
1775         ASSERT_EQ(group_count, returned_group_count);
1776 
1777         std::vector<VkPhysicalDeviceGroupProperties> group_props{};
1778         group_props.resize(group_count, VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
1779         ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props.data()));
1780         ASSERT_EQ(group_count, returned_group_count);
1781 
1782         // Make sure each physical device shows up in a group, but only once
1783         std::array<bool, max_physical_device_count> found{false};
1784         for (uint32_t group = 0; group < group_count; ++group) {
1785             for (uint32_t g_dev = 0; g_dev < group_props[group].physicalDeviceCount; ++g_dev) {
1786                 for (uint32_t dev = 0; dev < max_physical_device_count; ++dev) {
1787                     if (physical_devices[dev] == group_props[group].physicalDevices[g_dev]) {
1788                         ASSERT_EQ(false, found[dev]);
1789                         found[dev] = true;
1790                         break;
1791                     }
1792                 }
1793             }
1794         }
1795         for (uint32_t dev = 0; dev < max_physical_device_count; ++dev) {
1796             ASSERT_EQ(true, found[dev]);
1797         }
1798         for (auto& group : group_props) {
1799             VkDeviceGroupDeviceCreateInfo group_info{};
1800             group_info.sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO;
1801             group_info.physicalDeviceCount = group.physicalDeviceCount;
1802             group_info.pPhysicalDevices = &group.physicalDevices[0];
1803             DeviceWrapper dev{inst};
1804             dev.create_info.dev.pNext = &group_info;
1805             dev.CheckCreate(group.physicalDevices[0]);
1806         }
1807     }
1808     driver.add_instance_extension({VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME});
1809     // Extension
1810     {
1811         InstWrapper inst{env.vulkan_functions};
1812         inst.create_info.add_extension("VK_KHR_device_group_creation");
1813         inst.CheckCreate();
1814 
1815         auto physical_devices = std::vector<VkPhysicalDevice>(max_physical_device_count);
1816         uint32_t returned_phys_dev_count = max_physical_device_count;
1817         ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &returned_phys_dev_count, physical_devices.data()));
1818         handle_assert_has_values(physical_devices);
1819 
1820         PFN_vkEnumeratePhysicalDeviceGroupsKHR vkEnumeratePhysicalDeviceGroupsKHR = inst.load("vkEnumeratePhysicalDeviceGroupsKHR");
1821 
1822         uint32_t group_count = static_cast<uint32_t>(driver.physical_device_groups.size());
1823         uint32_t returned_group_count = 0;
1824         ASSERT_EQ(VK_SUCCESS, vkEnumeratePhysicalDeviceGroupsKHR(inst, &returned_group_count, nullptr));
1825         ASSERT_EQ(group_count, returned_group_count);
1826 
1827         std::vector<VkPhysicalDeviceGroupProperties> group_props{};
1828         group_props.resize(group_count, VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
1829         ASSERT_EQ(VK_SUCCESS, vkEnumeratePhysicalDeviceGroupsKHR(inst, &returned_group_count, group_props.data()));
1830         ASSERT_EQ(group_count, returned_group_count);
1831 
1832         // Make sure each physical device shows up in a group, but only once
1833         std::array<bool, max_physical_device_count> found{false};
1834         for (uint32_t group = 0; group < group_count; ++group) {
1835             for (uint32_t g_dev = 0; g_dev < group_props[group].physicalDeviceCount; ++g_dev) {
1836                 for (uint32_t dev = 0; dev < max_physical_device_count; ++dev) {
1837                     if (physical_devices[dev] == group_props[group].physicalDevices[g_dev]) {
1838                         ASSERT_EQ(false, found[dev]);
1839                         found[dev] = true;
1840                         break;
1841                     }
1842                 }
1843             }
1844         }
1845         for (uint32_t dev = 0; dev < max_physical_device_count; ++dev) {
1846             ASSERT_EQ(true, found[dev]);
1847         }
1848         for (auto& group : group_props) {
1849             VkDeviceGroupDeviceCreateInfo group_info{};
1850             group_info.sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO;
1851             group_info.physicalDeviceCount = group.physicalDeviceCount;
1852             group_info.pPhysicalDevices = &group.physicalDevices[0];
1853             DeviceWrapper dev{inst};
1854             dev.create_info.dev.pNext = &group_info;
1855             dev.CheckCreate(group.physicalDevices[0]);
1856         }
1857     }
1858 }
1859 
TEST(EnumeratePhysicalDeviceGroups, TwoCallIncomplete)1860 TEST(EnumeratePhysicalDeviceGroups, TwoCallIncomplete) {
1861     FrameworkEnvironment env{};
1862     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1))
1863                        .set_min_icd_interface_version(5)
1864                        .set_icd_api_version(VK_API_VERSION_1_1)
1865                        .add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
1866 
1867     // ICD contains 3 devices in two groups
1868     for (size_t i = 0; i < 3; i++) {
1869         driver.physical_devices.emplace_back(std::string("physical_device_") + std::to_string(i));
1870         driver.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
1871         driver.physical_devices.back().properties.apiVersion = VK_API_VERSION_1_1;
1872     }
1873     driver.physical_device_groups.emplace_back(driver.physical_devices[0]);
1874     driver.physical_device_groups.back().use_physical_device(driver.physical_devices[1]);
1875     driver.physical_device_groups.emplace_back(driver.physical_devices[2]);
1876 
1877     // Core function
1878     {
1879         InstWrapper inst{env.vulkan_functions};
1880         inst.create_info.set_api_version(VK_API_VERSION_1_1);
1881         inst.CheckCreate();
1882 
1883         uint32_t group_count = static_cast<uint32_t>(driver.physical_device_groups.size());
1884         uint32_t returned_group_count = 0;
1885         ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, nullptr));
1886         ASSERT_EQ(group_count, returned_group_count);
1887 
1888         returned_group_count = 1;
1889         std::array<VkPhysicalDeviceGroupProperties, 1> group_props{};
1890         group_props[0].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES;
1891         ASSERT_EQ(VK_INCOMPLETE, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props.data()));
1892         ASSERT_EQ(1U, returned_group_count);
1893 
1894         returned_group_count = 2;
1895         std::array<VkPhysicalDeviceGroupProperties, 2> group_props_2{};
1896         group_props_2[0].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES;
1897         group_props_2[1].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES;
1898         ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props_2.data()));
1899         ASSERT_EQ(2U, returned_group_count);
1900 
1901         // Make sure the incomplete group items appear in the complete group
1902         for (uint32_t inc_group = 0; inc_group < 1; ++inc_group) {
1903             bool found = false;
1904             for (uint32_t full_group = 0; full_group < 2; ++full_group) {
1905                 if (group_props[inc_group].physicalDeviceCount == group_props_2[full_group].physicalDeviceCount &&
1906                     group_props[inc_group].physicalDevices[0] == group_props_2[full_group].physicalDevices[0] &&
1907                     group_props[inc_group].physicalDevices[1] == group_props_2[full_group].physicalDevices[1]) {
1908                     found = true;
1909                     break;
1910                 }
1911             }
1912             ASSERT_EQ(true, found);
1913         }
1914         for (auto& group : group_props) {
1915             VkDeviceGroupDeviceCreateInfo group_info{};
1916             group_info.sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO;
1917             group_info.physicalDeviceCount = group.physicalDeviceCount;
1918             group_info.pPhysicalDevices = &group.physicalDevices[0];
1919             DeviceWrapper dev{inst};
1920             dev.create_info.dev.pNext = &group_info;
1921             dev.CheckCreate(group.physicalDevices[0]);
1922         }
1923     }
1924     driver.add_instance_extension({VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME});
1925     // Extension
1926     {
1927         InstWrapper inst{env.vulkan_functions};
1928         inst.create_info.add_extension("VK_KHR_device_group_creation");
1929         inst.CheckCreate();
1930 
1931         PFN_vkEnumeratePhysicalDeviceGroupsKHR vkEnumeratePhysicalDeviceGroupsKHR = inst.load("vkEnumeratePhysicalDeviceGroupsKHR");
1932 
1933         uint32_t group_count = static_cast<uint32_t>(driver.physical_device_groups.size());
1934         uint32_t returned_group_count = 0;
1935         ASSERT_EQ(VK_SUCCESS, vkEnumeratePhysicalDeviceGroupsKHR(inst, &returned_group_count, nullptr));
1936         ASSERT_EQ(group_count, returned_group_count);
1937 
1938         returned_group_count = 1;
1939         std::array<VkPhysicalDeviceGroupProperties, 1> group_props{};
1940         group_props[0].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES;
1941         ASSERT_EQ(VK_INCOMPLETE, vkEnumeratePhysicalDeviceGroupsKHR(inst, &returned_group_count, group_props.data()));
1942         ASSERT_EQ(1U, returned_group_count);
1943 
1944         returned_group_count = 2;
1945         std::array<VkPhysicalDeviceGroupProperties, 2> group_props_2{};
1946         group_props_2[0].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES;
1947         group_props_2[1].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES;
1948         ASSERT_EQ(VK_SUCCESS, vkEnumeratePhysicalDeviceGroupsKHR(inst, &returned_group_count, group_props_2.data()));
1949         ASSERT_EQ(2U, returned_group_count);
1950 
1951         // Make sure the incomplete group items appear in the complete group
1952         for (uint32_t inc_group = 0; inc_group < 1; ++inc_group) {
1953             bool found = false;
1954             for (uint32_t full_group = 0; full_group < 2; ++full_group) {
1955                 if (group_props[inc_group].physicalDeviceCount == group_props_2[full_group].physicalDeviceCount &&
1956                     group_props[inc_group].physicalDevices[0] == group_props_2[full_group].physicalDevices[0] &&
1957                     group_props[inc_group].physicalDevices[1] == group_props_2[full_group].physicalDevices[1]) {
1958                     found = true;
1959                     break;
1960                 }
1961             }
1962             ASSERT_EQ(true, found);
1963         }
1964         for (auto& group : group_props) {
1965             VkDeviceGroupDeviceCreateInfo group_info{};
1966             group_info.sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO;
1967             group_info.physicalDeviceCount = group.physicalDeviceCount;
1968             group_info.pPhysicalDevices = &group.physicalDevices[0];
1969             DeviceWrapper dev{inst};
1970             dev.create_info.dev.pNext = &group_info;
1971             dev.CheckCreate(group.physicalDevices[0]);
1972         }
1973     }
1974 }
1975 
1976 // Call the core vkEnumeratePhysicalDeviceGroups and the extension
1977 // vkEnumeratePhysicalDeviceGroupsKHR, and make sure they return the same info.
TEST(EnumeratePhysicalDeviceGroups, TestCoreVersusExtensionSameReturns)1978 TEST(EnumeratePhysicalDeviceGroups, TestCoreVersusExtensionSameReturns) {
1979     FrameworkEnvironment env{};
1980     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1))
1981                        .set_min_icd_interface_version(5)
1982                        .set_icd_api_version(VK_API_VERSION_1_1)
1983                        .add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME})
1984                        .add_instance_extension({VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME});
1985 
1986     // Generate the devices
1987     for (size_t i = 0; i < 6; i++) {
1988         driver.physical_devices.emplace_back(std::string("physical_device_") + std::to_string(i));
1989         driver.physical_devices.back().properties.apiVersion = VK_API_VERSION_1_1;
1990     }
1991 
1992     // Generate the starting groups
1993     driver.physical_device_groups.emplace_back(driver.physical_devices[0]);
1994     driver.physical_device_groups.emplace_back(driver.physical_devices[1]);
1995     driver.physical_device_groups.back()
1996         .use_physical_device(driver.physical_devices[2])
1997         .use_physical_device(driver.physical_devices[3]);
1998     driver.physical_device_groups.emplace_back(driver.physical_devices[4]);
1999     driver.physical_device_groups.back().use_physical_device(driver.physical_devices[5]);
2000 
2001     uint32_t expected_counts[3] = {1, 3, 2};
2002     uint32_t core_group_count = 0;
2003     std::vector<VkPhysicalDeviceGroupProperties> core_group_props{};
2004     uint32_t ext_group_count = 0;
2005     std::vector<VkPhysicalDeviceGroupProperties> ext_group_props{};
2006 
2007     InstWrapper inst{env.vulkan_functions};
2008     inst.create_info.set_api_version(1, 1, 0);
2009     inst.create_info.add_extension("VK_KHR_device_group_creation");
2010     inst.CheckCreate();
2011 
2012     // Core function
2013     core_group_count = static_cast<uint32_t>(driver.physical_device_groups.size());
2014     uint32_t returned_group_count = 0;
2015     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, nullptr));
2016     ASSERT_EQ(core_group_count, returned_group_count);
2017 
2018     core_group_props.resize(returned_group_count,
2019                             VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
2020     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, core_group_props.data()));
2021     ASSERT_EQ(core_group_count, returned_group_count);
2022 
2023     PFN_vkEnumeratePhysicalDeviceGroupsKHR vkEnumeratePhysicalDeviceGroupsKHR = inst.load("vkEnumeratePhysicalDeviceGroupsKHR");
2024 
2025     ext_group_count = static_cast<uint32_t>(driver.physical_device_groups.size());
2026     returned_group_count = 0;
2027     ASSERT_EQ(VK_SUCCESS, vkEnumeratePhysicalDeviceGroupsKHR(inst, &returned_group_count, nullptr));
2028     ASSERT_EQ(ext_group_count, returned_group_count);
2029 
2030     ext_group_props.resize(returned_group_count,
2031                            VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
2032     ASSERT_EQ(VK_SUCCESS, vkEnumeratePhysicalDeviceGroupsKHR(inst, &returned_group_count, ext_group_props.data()));
2033     ASSERT_EQ(ext_group_count, returned_group_count);
2034 
2035     // Make sure data from each matches
2036     ASSERT_EQ(core_group_count, 3U);
2037     ASSERT_EQ(ext_group_count, 3U);
2038     for (uint32_t group = 0; group < core_group_count; ++group) {
2039         ASSERT_EQ(core_group_props[group].physicalDeviceCount, expected_counts[group]);
2040         ASSERT_EQ(ext_group_props[group].physicalDeviceCount, expected_counts[group]);
2041         for (uint32_t dev = 0; dev < core_group_props[group].physicalDeviceCount; ++dev) {
2042             ASSERT_EQ(core_group_props[group].physicalDevices[dev], ext_group_props[group].physicalDevices[dev]);
2043         }
2044     }
2045     // Make sure no physical device appears in more than one group
2046     for (uint32_t group1 = 0; group1 < core_group_count; ++group1) {
2047         for (uint32_t group2 = group1 + 1; group2 < core_group_count; ++group2) {
2048             for (uint32_t dev1 = 0; dev1 < core_group_props[group1].physicalDeviceCount; ++dev1) {
2049                 for (uint32_t dev2 = 0; dev2 < core_group_props[group1].physicalDeviceCount; ++dev2) {
2050                     ASSERT_NE(core_group_props[group1].physicalDevices[dev1], core_group_props[group2].physicalDevices[dev2]);
2051                 }
2052             }
2053         }
2054     }
2055     for (auto& group : core_group_props) {
2056         VkDeviceGroupDeviceCreateInfo group_info{};
2057         group_info.sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO;
2058         group_info.physicalDeviceCount = group.physicalDeviceCount;
2059         group_info.pPhysicalDevices = &group.physicalDevices[0];
2060         DeviceWrapper dev{inst};
2061         dev.create_info.dev.pNext = &group_info;
2062         dev.CheckCreate(group.physicalDevices[0]);
2063     }
2064 }
2065 
2066 // Start with 6 devices in 3 different groups, and then add a group,
2067 // querying vkEnumeratePhysicalDeviceGroups before and after the add.
TEST(EnumeratePhysicalDeviceGroups, CallThriceAddGroupInBetween)2068 TEST(EnumeratePhysicalDeviceGroups, CallThriceAddGroupInBetween) {
2069     FrameworkEnvironment env{};
2070     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1))
2071                        .set_min_icd_interface_version(5)
2072                        .set_icd_api_version(VK_API_VERSION_1_1);
2073 
2074     // Generate the devices
2075     for (size_t i = 0; i < 7; i++) {
2076         driver.physical_devices.emplace_back(std::string("physical_device_") + std::to_string(i));
2077         driver.physical_devices.back().properties.apiVersion = VK_API_VERSION_1_1;
2078     }
2079 
2080     // Generate the starting groups
2081     driver.physical_device_groups.emplace_back(driver.physical_devices[0]);
2082     driver.physical_device_groups.emplace_back(driver.physical_devices[1]);
2083     driver.physical_device_groups.back()
2084         .use_physical_device(driver.physical_devices[2])
2085         .use_physical_device(driver.physical_devices[3]);
2086     driver.physical_device_groups.emplace_back(driver.physical_devices[4]);
2087     driver.physical_device_groups.back().use_physical_device(driver.physical_devices[5]);
2088 
2089     uint32_t before_expected_counts[3] = {1, 3, 2};
2090     uint32_t after_expected_counts[4] = {1, 3, 1, 2};
2091     uint32_t before_group_count = 3;
2092     uint32_t after_group_count = 4;
2093     uint32_t returned_group_count = 0;
2094 
2095     InstWrapper inst{env.vulkan_functions};
2096     inst.create_info.set_api_version(1, 1, 0);
2097     inst.CheckCreate();
2098 
2099     std::vector<VkPhysicalDeviceGroupProperties> group_props_before{};
2100     group_props_before.resize(before_group_count,
2101                               VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
2102     returned_group_count = before_group_count;
2103     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props_before.data()));
2104     ASSERT_EQ(before_group_count, returned_group_count);
2105     for (uint32_t group = 0; group < before_group_count; ++group) {
2106         ASSERT_EQ(group_props_before[group].physicalDeviceCount, before_expected_counts[group]);
2107     }
2108 
2109     // Insert new group after first two
2110     driver.physical_device_groups.insert(driver.physical_device_groups.begin() + 2, driver.physical_devices[6]);
2111 
2112     std::vector<VkPhysicalDeviceGroupProperties> group_props_after{};
2113     group_props_after.resize(before_group_count,
2114                              VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
2115     ASSERT_EQ(VK_INCOMPLETE, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props_after.data()));
2116     ASSERT_EQ(before_group_count, returned_group_count);
2117     for (uint32_t group = 0; group < before_group_count; ++group) {
2118         ASSERT_EQ(group_props_after[group].physicalDeviceCount, after_expected_counts[group]);
2119     }
2120 
2121     group_props_after.resize(after_group_count,
2122                              VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
2123     returned_group_count = after_group_count;
2124     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props_after.data()));
2125     ASSERT_EQ(after_group_count, returned_group_count);
2126     for (uint32_t group = 0; group < after_group_count; ++group) {
2127         ASSERT_EQ(group_props_after[group].physicalDeviceCount, after_expected_counts[group]);
2128     }
2129 
2130     // Make sure all devices in the old group info are still found in the new group info
2131     for (uint32_t group1 = 0; group1 < group_props_before.size(); ++group1) {
2132         for (uint32_t group2 = 0; group2 < group_props_after.size(); ++group2) {
2133             if (group_props_before[group1].physicalDeviceCount == group_props_after[group2].physicalDeviceCount) {
2134                 uint32_t found_count = 0;
2135                 bool found = false;
2136                 for (uint32_t dev1 = 0; dev1 < group_props_before[group1].physicalDeviceCount; ++dev1) {
2137                     found = false;
2138                     for (uint32_t dev2 = 0; dev2 < group_props_after[group2].physicalDeviceCount; ++dev2) {
2139                         if (group_props_before[group1].physicalDevices[dev1] == group_props_after[group2].physicalDevices[dev2]) {
2140                             found_count++;
2141                             found = true;
2142                             break;
2143                         }
2144                     }
2145                 }
2146                 ASSERT_EQ(found, found_count == group_props_before[group1].physicalDeviceCount);
2147             }
2148         }
2149     }
2150     for (auto& group : group_props_after) {
2151         VkDeviceGroupDeviceCreateInfo group_info{};
2152         group_info.sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO;
2153         group_info.physicalDeviceCount = group.physicalDeviceCount;
2154         group_info.pPhysicalDevices = &group.physicalDevices[0];
2155         DeviceWrapper dev{inst};
2156         dev.create_info.dev.pNext = &group_info;
2157         dev.CheckCreate(group.physicalDevices[0]);
2158     }
2159 }
2160 
2161 // Start with 7 devices in 4 different groups, and then remove a group,
2162 // querying vkEnumeratePhysicalDeviceGroups before and after the remove.
TEST(EnumeratePhysicalDeviceGroups, CallTwiceRemoveGroupInBetween)2163 TEST(EnumeratePhysicalDeviceGroups, CallTwiceRemoveGroupInBetween) {
2164     FrameworkEnvironment env{};
2165     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1))
2166                        .set_min_icd_interface_version(5)
2167                        .set_icd_api_version(VK_API_VERSION_1_1);
2168 
2169     // Generate the devices
2170     for (size_t i = 0; i < 7; i++) {
2171         driver.physical_devices.emplace_back(std::string("physical_device_") + std::to_string(i));
2172         driver.physical_devices.back().properties.apiVersion = VK_API_VERSION_1_1;
2173     }
2174 
2175     // Generate the starting groups
2176     driver.physical_device_groups.emplace_back(driver.physical_devices[0]);
2177     driver.physical_device_groups.emplace_back(driver.physical_devices[1]);
2178     driver.physical_device_groups.back()
2179         .use_physical_device(driver.physical_devices[2])
2180         .use_physical_device(driver.physical_devices[3]);
2181     driver.physical_device_groups.emplace_back(driver.physical_devices[4]);
2182     driver.physical_device_groups.emplace_back(driver.physical_devices[5]);
2183     driver.physical_device_groups.back().use_physical_device(driver.physical_devices[6]);
2184 
2185     uint32_t before_expected_counts[4] = {1, 3, 1, 2};
2186     uint32_t after_expected_counts[3] = {1, 3, 2};
2187     uint32_t before_group_count = 4;
2188     uint32_t after_group_count = 3;
2189     uint32_t returned_group_count = 0;
2190 
2191     InstWrapper inst{env.vulkan_functions};
2192     inst.create_info.set_api_version(1, 1, 0);
2193     inst.CheckCreate();
2194 
2195     std::vector<VkPhysicalDeviceGroupProperties> group_props_before{};
2196     group_props_before.resize(before_group_count,
2197                               VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
2198     returned_group_count = before_group_count;
2199     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props_before.data()));
2200     ASSERT_EQ(before_group_count, returned_group_count);
2201     for (uint32_t group = 0; group < before_group_count; ++group) {
2202         ASSERT_EQ(group_props_before[group].physicalDeviceCount, before_expected_counts[group]);
2203     }
2204 
2205     // Insert new group after first two
2206     driver.physical_device_groups.erase(driver.physical_device_groups.begin() + 2);
2207 
2208     std::vector<VkPhysicalDeviceGroupProperties> group_props_after{};
2209     group_props_after.resize(after_group_count,
2210                              VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
2211     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props_after.data()));
2212     ASSERT_EQ(after_group_count, returned_group_count);
2213     for (uint32_t group = 0; group < after_group_count; ++group) {
2214         ASSERT_EQ(group_props_after[group].physicalDeviceCount, after_expected_counts[group]);
2215     }
2216 
2217     // Make sure all devices in the new group info are found in the old group info
2218     for (uint32_t group1 = 0; group1 < group_props_after.size(); ++group1) {
2219         for (uint32_t group2 = 0; group2 < group_props_before.size(); ++group2) {
2220             if (group_props_after[group1].physicalDeviceCount == group_props_before[group2].physicalDeviceCount) {
2221                 uint32_t found_count = 0;
2222                 bool found = false;
2223                 for (uint32_t dev1 = 0; dev1 < group_props_after[group1].physicalDeviceCount; ++dev1) {
2224                     found = false;
2225                     for (uint32_t dev2 = 0; dev2 < group_props_before[group2].physicalDeviceCount; ++dev2) {
2226                         if (group_props_after[group1].physicalDevices[dev1] == group_props_before[group2].physicalDevices[dev2]) {
2227                             found_count++;
2228                             found = true;
2229                             break;
2230                         }
2231                     }
2232                 }
2233                 ASSERT_EQ(found, found_count == group_props_after[group1].physicalDeviceCount);
2234             }
2235         }
2236     }
2237     for (auto& group : group_props_after) {
2238         VkDeviceGroupDeviceCreateInfo group_info{};
2239         group_info.sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO;
2240         group_info.physicalDeviceCount = group.physicalDeviceCount;
2241         group_info.pPhysicalDevices = &group.physicalDevices[0];
2242         DeviceWrapper dev{inst};
2243         dev.create_info.dev.pNext = &group_info;
2244         dev.CheckCreate(group.physicalDevices[0]);
2245     }
2246 }
2247 
2248 // Start with 6 devices in 3 different groups, and then add a device to the middle group,
2249 // querying vkEnumeratePhysicalDeviceGroups before and after the add.
TEST(EnumeratePhysicalDeviceGroups, CallTwiceAddDeviceInBetween)2250 TEST(EnumeratePhysicalDeviceGroups, CallTwiceAddDeviceInBetween) {
2251     FrameworkEnvironment env{};
2252     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1))
2253                        .set_min_icd_interface_version(5)
2254                        .set_icd_api_version(VK_API_VERSION_1_1);
2255 
2256     // Generate the devices
2257     for (size_t i = 0; i < 7; i++) {
2258         driver.physical_devices.emplace_back(std::string("physical_device_") + std::to_string(i));
2259         driver.physical_devices.back().properties.apiVersion = VK_API_VERSION_1_1;
2260     }
2261 
2262     // Generate the starting groups
2263     driver.physical_device_groups.emplace_back(driver.physical_devices[0]);
2264     driver.physical_device_groups.emplace_back(driver.physical_devices[1]);
2265     driver.physical_device_groups.back()
2266         .use_physical_device(driver.physical_devices[2])
2267         .use_physical_device(driver.physical_devices[3]);
2268     driver.physical_device_groups.emplace_back(driver.physical_devices[4]);
2269     driver.physical_device_groups.back().use_physical_device(driver.physical_devices[5]);
2270 
2271     uint32_t expected_group_count = 3;
2272     uint32_t before_expected_counts[3] = {1, 3, 2};
2273     uint32_t after_expected_counts[3] = {1, 4, 2};
2274     uint32_t returned_group_count = 0;
2275 
2276     InstWrapper inst{env.vulkan_functions};
2277     inst.create_info.set_api_version(1, 1, 0);
2278     inst.CheckCreate();
2279 
2280     std::vector<VkPhysicalDeviceGroupProperties> group_props_before{};
2281     group_props_before.resize(expected_group_count,
2282                               VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
2283     returned_group_count = expected_group_count;
2284     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props_before.data()));
2285     ASSERT_EQ(expected_group_count, returned_group_count);
2286     for (uint32_t group = 0; group < expected_group_count; ++group) {
2287         ASSERT_EQ(group_props_before[group].physicalDeviceCount, before_expected_counts[group]);
2288     }
2289 
2290     // Insert new device to 2nd group
2291     driver.physical_device_groups[1].use_physical_device(driver.physical_devices[6]);
2292 
2293     std::vector<VkPhysicalDeviceGroupProperties> group_props_after{};
2294     group_props_after.resize(expected_group_count,
2295                              VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
2296     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props_after.data()));
2297     ASSERT_EQ(expected_group_count, returned_group_count);
2298     for (uint32_t group = 0; group < expected_group_count; ++group) {
2299         ASSERT_EQ(group_props_after[group].physicalDeviceCount, after_expected_counts[group]);
2300     }
2301 
2302     // Make sure all devices in the old group info are still found in the new group info
2303     for (uint32_t group1 = 0; group1 < group_props_before.size(); ++group1) {
2304         for (uint32_t group2 = 0; group2 < group_props_after.size(); ++group2) {
2305             uint32_t found_count = 0;
2306             bool found = false;
2307             for (uint32_t dev1 = 0; dev1 < group_props_before[group1].physicalDeviceCount; ++dev1) {
2308                 found = false;
2309                 for (uint32_t dev2 = 0; dev2 < group_props_after[group2].physicalDeviceCount; ++dev2) {
2310                     if (group_props_before[group1].physicalDevices[dev1] == group_props_after[group2].physicalDevices[dev2]) {
2311                         found_count++;
2312                         found = true;
2313                         break;
2314                     }
2315                 }
2316             }
2317             ASSERT_EQ(found, found_count != 0 && found_count == before_expected_counts[group1]);
2318             if (found) {
2319                 break;
2320             }
2321         }
2322     }
2323     for (auto& group : group_props_after) {
2324         VkDeviceGroupDeviceCreateInfo group_info{};
2325         group_info.sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO;
2326         group_info.physicalDeviceCount = group.physicalDeviceCount;
2327         group_info.pPhysicalDevices = &group.physicalDevices[0];
2328         DeviceWrapper dev{inst};
2329         dev.create_info.dev.pNext = &group_info;
2330         dev.CheckCreate(group.physicalDevices[0]);
2331     }
2332 }
2333 
2334 // Start with 6 devices in 3 different groups, and then remove a device to the middle group,
2335 // querying vkEnumeratePhysicalDeviceGroups before and after the remove.
TEST(EnumeratePhysicalDeviceGroups, CallTwiceRemoveDeviceInBetween)2336 TEST(EnumeratePhysicalDeviceGroups, CallTwiceRemoveDeviceInBetween) {
2337     FrameworkEnvironment env{};
2338     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1))
2339                        .set_min_icd_interface_version(5)
2340                        .set_icd_api_version(VK_API_VERSION_1_1);
2341 
2342     // Generate the devices
2343     for (size_t i = 0; i < 6; i++) {
2344         driver.physical_devices.emplace_back(std::string("physical_device_") + std::to_string(i));
2345         driver.physical_devices.back().properties.apiVersion = VK_API_VERSION_1_1;
2346     }
2347 
2348     // Generate the starting groups
2349     driver.physical_device_groups.emplace_back(driver.physical_devices[0]);
2350     driver.physical_device_groups.emplace_back(driver.physical_devices[1]);
2351     driver.physical_device_groups.back()
2352         .use_physical_device(driver.physical_devices[2])
2353         .use_physical_device(driver.physical_devices[3]);
2354     driver.physical_device_groups.emplace_back(driver.physical_devices[4]);
2355     driver.physical_device_groups.back().use_physical_device(driver.physical_devices[5]);
2356 
2357     uint32_t before_expected_counts[3] = {1, 3, 2};
2358     uint32_t after_expected_counts[3] = {1, 2, 2};
2359     uint32_t expected_group_count = 3;
2360     uint32_t returned_group_count = 0;
2361 
2362     InstWrapper inst{env.vulkan_functions};
2363     inst.create_info.set_api_version(1, 1, 0);
2364     inst.CheckCreate();
2365 
2366     std::vector<VkPhysicalDeviceGroupProperties> group_props_before{};
2367     group_props_before.resize(expected_group_count,
2368                               VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
2369     returned_group_count = expected_group_count;
2370     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props_before.data()));
2371     ASSERT_EQ(expected_group_count, returned_group_count);
2372     printf("Before:\n");
2373     for (uint32_t group = 0; group < expected_group_count; ++group) {
2374         printf("  Group %u:\n", group);
2375         ASSERT_EQ(group_props_before[group].physicalDeviceCount, before_expected_counts[group]);
2376         for (uint32_t dev = 0; dev < group_props_before[group].physicalDeviceCount; ++dev) {
2377             printf("    Dev %u: %p\n", dev, group_props_before[group].physicalDevices[dev]);
2378         }
2379     }
2380 
2381     // Remove middle device in middle group
2382     driver.physical_device_groups[1].physical_device_handles.erase(
2383         driver.physical_device_groups[1].physical_device_handles.begin() + 1);
2384 
2385     std::vector<VkPhysicalDeviceGroupProperties> group_props_after{};
2386     group_props_after.resize(expected_group_count,
2387                              VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
2388     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props_after.data()));
2389     ASSERT_EQ(expected_group_count, returned_group_count);
2390     printf("After:\n");
2391     for (uint32_t group = 0; group < expected_group_count; ++group) {
2392         printf("  Group %u:\n", group);
2393         ASSERT_EQ(group_props_after[group].physicalDeviceCount, after_expected_counts[group]);
2394         for (uint32_t dev = 0; dev < group_props_after[group].physicalDeviceCount; ++dev) {
2395             printf("    Dev %u: %p\n", dev, group_props_after[group].physicalDevices[dev]);
2396         }
2397     }
2398 
2399     // Make sure all devices in the new group info are found in the old group info
2400     for (uint32_t group1 = 0; group1 < group_props_after.size(); ++group1) {
2401         for (uint32_t group2 = 0; group2 < group_props_before.size(); ++group2) {
2402             uint32_t found_count = 0;
2403             bool found = false;
2404             for (uint32_t dev1 = 0; dev1 < group_props_after[group1].physicalDeviceCount; ++dev1) {
2405                 found = false;
2406                 for (uint32_t dev2 = 0; dev2 < group_props_before[group2].physicalDeviceCount; ++dev2) {
2407                     if (group_props_after[group1].physicalDevices[dev1] == group_props_before[group2].physicalDevices[dev2]) {
2408                         found_count++;
2409                         found = true;
2410                         break;
2411                     }
2412                 }
2413             }
2414             ASSERT_EQ(found, found_count != 0 && found_count == after_expected_counts[group1]);
2415             if (found) {
2416                 break;
2417             }
2418         }
2419     }
2420     for (auto& group : group_props_after) {
2421         VkDeviceGroupDeviceCreateInfo group_info{};
2422         group_info.sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO;
2423         group_info.physicalDeviceCount = group.physicalDeviceCount;
2424         group_info.pPhysicalDevices = &group.physicalDevices[0];
2425         DeviceWrapper dev{inst};
2426         dev.create_info.dev.pNext = &group_info;
2427         dev.CheckCreate(group.physicalDevices[0]);
2428     }
2429 }
2430 
2431 // Start with 9 devices but only some in 3 different groups, add and remove
2432 // various devices and groups while querying in between.
TEST(EnumeratePhysicalDeviceGroups, MultipleAddRemoves)2433 TEST(EnumeratePhysicalDeviceGroups, MultipleAddRemoves) {
2434     FrameworkEnvironment env{};
2435     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1))
2436                        .set_min_icd_interface_version(5)
2437                        .set_icd_api_version(VK_API_VERSION_1_1);
2438 
2439     // Generate the devices
2440     for (size_t i = 0; i < 9; i++) {
2441         driver.physical_devices.emplace_back(std::string("physical_device_") + std::to_string(i));
2442         driver.physical_devices.back().properties.apiVersion = VK_API_VERSION_1_1;
2443     }
2444 
2445     // Generate the starting groups
2446     driver.physical_device_groups.emplace_back(driver.physical_devices[0]);
2447     driver.physical_device_groups.emplace_back(driver.physical_devices[1]);
2448     driver.physical_device_groups.back()
2449         .use_physical_device(driver.physical_devices[2])
2450         .use_physical_device(driver.physical_devices[3]);
2451     driver.physical_device_groups.emplace_back(driver.physical_devices[4]);
2452     driver.physical_device_groups.back().use_physical_device(driver.physical_devices[5]);
2453 
2454     uint32_t before_expected_counts[3] = {1, 3, 2};
2455     uint32_t after_add_group_expected_counts[4] = {1, 3, 1, 2};
2456     uint32_t after_remove_dev_expected_counts[4] = {1, 2, 1, 2};
2457     uint32_t after_remove_group_expected_counts[3] = {2, 1, 2};
2458     uint32_t after_add_dev_expected_counts[3] = {2, 1, 4};
2459     uint32_t before_group_count = 3;
2460     uint32_t after_group_count = 4;
2461     uint32_t returned_group_count = 0;
2462 
2463     InstWrapper inst{env.vulkan_functions};
2464     inst.create_info.set_api_version(1, 1, 0);
2465     inst.CheckCreate();
2466 
2467     // Should be: 3 Groups { { 0 }, { 1, 2, 3 }, { 4, 5 } }
2468     std::vector<VkPhysicalDeviceGroupProperties> group_props_before{};
2469     group_props_before.resize(before_group_count,
2470                               VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
2471     returned_group_count = before_group_count;
2472     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props_before.data()));
2473     ASSERT_EQ(before_group_count, returned_group_count);
2474     for (uint32_t group = 0; group < before_group_count; ++group) {
2475         ASSERT_EQ(group_props_before[group].physicalDeviceCount, before_expected_counts[group]);
2476     }
2477 
2478     // Insert new group after first two
2479     driver.physical_device_groups.insert(driver.physical_device_groups.begin() + 2, driver.physical_devices[6]);
2480 
2481     // Should be: 4 Groups { { 0 }, { 1, 2, 3 }, { 6 }, { 4, 5 } }
2482     std::vector<VkPhysicalDeviceGroupProperties> group_props_after_add_group{};
2483     group_props_after_add_group.resize(after_group_count,
2484                                        VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
2485     returned_group_count = after_group_count;
2486     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props_after_add_group.data()));
2487     ASSERT_EQ(after_group_count, returned_group_count);
2488     for (uint32_t group = 0; group < before_group_count; ++group) {
2489         ASSERT_EQ(group_props_after_add_group[group].physicalDeviceCount, after_add_group_expected_counts[group]);
2490     }
2491 
2492     // Remove first device in 2nd group
2493     driver.physical_device_groups[1].physical_device_handles.erase(
2494         driver.physical_device_groups[1].physical_device_handles.begin());
2495 
2496     // Should be: 4 Groups { { 0 }, { 2, 3 }, { 6 }, { 4, 5 } }
2497     std::vector<VkPhysicalDeviceGroupProperties> group_props_after_remove_device{};
2498     group_props_after_remove_device.resize(after_group_count,
2499                                            VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
2500     returned_group_count = after_group_count;
2501     ASSERT_EQ(VK_SUCCESS,
2502               inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props_after_remove_device.data()));
2503     ASSERT_EQ(after_group_count, returned_group_count);
2504     for (uint32_t group = 0; group < before_group_count; ++group) {
2505         ASSERT_EQ(group_props_after_remove_device[group].physicalDeviceCount, after_remove_dev_expected_counts[group]);
2506     }
2507 
2508     // Remove first group
2509     driver.physical_device_groups.erase(driver.physical_device_groups.begin());
2510 
2511     // Should be: 3 Groups { { 2, 3 }, { 6 }, { 4, 5 } }
2512     std::vector<VkPhysicalDeviceGroupProperties> group_props_after_remove_group{};
2513     group_props_after_remove_group.resize(before_group_count,
2514                                           VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
2515     returned_group_count = before_group_count;
2516     ASSERT_EQ(VK_SUCCESS,
2517               inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props_after_remove_group.data()));
2518     ASSERT_EQ(before_group_count, returned_group_count);
2519     for (uint32_t group = 0; group < before_group_count; ++group) {
2520         ASSERT_EQ(group_props_after_remove_group[group].physicalDeviceCount, after_remove_group_expected_counts[group]);
2521     }
2522 
2523     // Add two devices to last group
2524     driver.physical_device_groups.back()
2525         .use_physical_device(driver.physical_devices[7])
2526         .use_physical_device(driver.physical_devices[8]);
2527 
2528     // Should be: 3 Groups { { 2, 3 }, { 6 }, { 4, 5, 7, 8 } }
2529     std::vector<VkPhysicalDeviceGroupProperties> group_props_after_add_device{};
2530     group_props_after_add_device.resize(before_group_count,
2531                                         VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
2532     returned_group_count = before_group_count;
2533     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props_after_add_device.data()));
2534     ASSERT_EQ(before_group_count, returned_group_count);
2535     for (uint32_t group = 0; group < before_group_count; ++group) {
2536         ASSERT_EQ(group_props_after_add_device[group].physicalDeviceCount, after_add_dev_expected_counts[group]);
2537     }
2538     for (auto& group : group_props_after_add_device) {
2539         VkDeviceGroupDeviceCreateInfo group_info{};
2540         group_info.sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO;
2541         group_info.physicalDeviceCount = group.physicalDeviceCount;
2542         group_info.pPhysicalDevices = &group.physicalDevices[0];
2543         DeviceWrapper dev{inst};
2544         dev.create_info.dev.pNext = &group_info;
2545         dev.CheckCreate(group.physicalDevices[0]);
2546     }
2547 }
2548 
2549 // Fill in random but valid data into the device properties struct for the current physical device
FillInRandomDeviceProps(VkPhysicalDeviceProperties& props, VkPhysicalDeviceType dev_type, uint32_t api_vers, uint32_t vendor, uint32_t device)2550 void FillInRandomDeviceProps(VkPhysicalDeviceProperties& props, VkPhysicalDeviceType dev_type, uint32_t api_vers, uint32_t vendor,
2551                              uint32_t device) {
2552     props.apiVersion = api_vers;
2553     props.vendorID = vendor;
2554     props.deviceID = device;
2555     props.deviceType = dev_type;
2556     for (uint8_t idx = 0; idx < VK_UUID_SIZE; ++idx) {
2557         props.pipelineCacheUUID[idx] = static_cast<uint8_t>(rand() % 255);
2558     }
2559 }
2560 
2561 // Pass in a PNext that the fake ICD will fill in some data for.
TEST(EnumeratePhysicalDeviceGroups, FakePNext)2562 TEST(EnumeratePhysicalDeviceGroups, FakePNext) {
2563     FrameworkEnvironment env{};
2564 
2565     // ICD 0: Vulkan 1.1
2566     //   PhysDev 0: pd0, Discrete, Vulkan 1.1, Bus 7
2567     //   PhysDev 1: pd1, Integrated, Vulkan 1.1, Bus 3
2568     //   PhysDev 2: pd2, Discrete, Vulkan 1.1, Bus 6
2569     //   Group 0: PhysDev 0, PhysDev 2
2570     //   Group 1: PhysDev 1
2571     // ICD 1: Vulkan 1.1
2572     //   PhysDev 4: pd4, Discrete, Vulkan 1.1, Bus 1
2573     //   PhysDev 5: pd5, Discrete, Vulkan 1.1, Bus 4
2574     //   PhysDev 6: pd6, Discrete, Vulkan 1.1, Bus 2
2575     //   Group 0: PhysDev 5, PhysDev 6
2576     //   Group 1: PhysDev 4
2577     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, VK_API_VERSION_1_1));
2578     auto& cur_icd_0 = env.get_test_icd(0);
2579     cur_icd_0.set_icd_api_version(VK_API_VERSION_1_1);
2580     cur_icd_0.physical_devices.push_back({"pd0"});
2581     cur_icd_0.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2582     FillInRandomDeviceProps(cur_icd_0.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_API_VERSION_1_1,
2583                             888, 0xAAA001);
2584     cur_icd_0.physical_devices.push_back({"pd1"});
2585     cur_icd_0.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2586     FillInRandomDeviceProps(cur_icd_0.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
2587                             VK_API_VERSION_1_1, 888, 0xAAA002);
2588     cur_icd_0.physical_devices.push_back({"pd2"});
2589     cur_icd_0.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2590     FillInRandomDeviceProps(cur_icd_0.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_API_VERSION_1_1,
2591                             888, 0xAAA003);
2592     cur_icd_0.physical_device_groups.push_back({});
2593     cur_icd_0.physical_device_groups.back()
2594         .use_physical_device(cur_icd_0.physical_devices[0])
2595         .use_physical_device(cur_icd_0.physical_devices[2]);
2596     cur_icd_0.physical_device_groups.push_back({cur_icd_0.physical_devices[1]});
2597 
2598     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, VK_API_VERSION_1_1));
2599     auto& cur_icd_1 = env.get_test_icd(1);
2600     cur_icd_1.set_icd_api_version(VK_API_VERSION_1_1);
2601     cur_icd_1.physical_devices.push_back({"pd4"});
2602     cur_icd_1.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2603     FillInRandomDeviceProps(cur_icd_1.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_API_VERSION_1_1,
2604                             75, 0xCCCC001);
2605     cur_icd_1.physical_devices.push_back({"pd5"});
2606     cur_icd_1.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2607     FillInRandomDeviceProps(cur_icd_1.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_API_VERSION_1_1,
2608                             75, 0xCCCC002);
2609     cur_icd_1.physical_devices.push_back({"pd6"});
2610     cur_icd_1.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2611     FillInRandomDeviceProps(cur_icd_1.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_API_VERSION_1_1,
2612                             75, 0xCCCC003);
2613     cur_icd_1.physical_device_groups.push_back({});
2614     cur_icd_1.physical_device_groups.back()
2615         .use_physical_device(cur_icd_1.physical_devices[1])
2616         .use_physical_device(cur_icd_1.physical_devices[2]);
2617     cur_icd_1.physical_device_groups.push_back({cur_icd_1.physical_devices[0]});
2618 
2619     InstWrapper inst(env.vulkan_functions);
2620     inst.create_info.set_api_version(VK_API_VERSION_1_1);
2621     inst.CheckCreate();
2622 
2623     PFN_vkGetPhysicalDeviceProperties2 GetPhysDevProps2 = inst.load("vkGetPhysicalDeviceProperties2");
2624     ASSERT_NE(GetPhysDevProps2, nullptr);
2625 
2626     // NOTE: This is a fake struct to make sure the pNext chain is properly passed down to the ICD
2627     //       vkEnumeratePhysicalDeviceGroups.
2628     //       The two versions must match:
2629     //           "FakePNext" test in loader_regression_tests.cpp
2630     //           "test_vkEnumeratePhysicalDeviceGroups" in test_icd.cpp
2631     struct FakePnextSharedWithICD {
2632         VkStructureType sType;
2633         void* pNext;
2634         uint32_t value;
2635     };
2636 
2637     const uint32_t max_phys_dev_groups = 4;
2638     uint32_t group_count = max_phys_dev_groups;
2639     std::array<FakePnextSharedWithICD, max_phys_dev_groups> fake_structs;
2640     std::array<VkPhysicalDeviceGroupProperties, max_phys_dev_groups> physical_device_groups{};
2641     for (uint32_t group = 0; group < max_phys_dev_groups; ++group) {
2642         physical_device_groups[group].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES;
2643         fake_structs[group].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_PROPERTIES_EXT;
2644         physical_device_groups[group].pNext = &fake_structs[group];
2645     }
2646     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &group_count, physical_device_groups.data()));
2647     ASSERT_EQ(group_count, max_phys_dev_groups);
2648 
2649     // Value should get written to 0xDECAFBADD by the fake ICD
2650     for (uint32_t group = 0; group < max_phys_dev_groups; ++group) {
2651         ASSERT_EQ(fake_structs[group].value, 0xDECAFBAD);
2652     }
2653 }
2654 
TEST(ExtensionManual, ToolingProperties)2655 TEST(ExtensionManual, ToolingProperties) {
2656     VkPhysicalDeviceToolPropertiesEXT icd_tool_props{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TOOL_PROPERTIES_EXT,
2657                                                      nullptr,
2658                                                      "FakeICDTool",
2659                                                      "version_0_0_0_1.b",
2660                                                      VK_TOOL_PURPOSE_VALIDATION_BIT_EXT,
2661                                                      "This tool does not exist",
2662                                                      "No-Layer"};
2663     {  // No support in driver
2664         FrameworkEnvironment env{};
2665         env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device({});
2666 
2667         InstWrapper inst{env.vulkan_functions};
2668         inst.CheckCreate();
2669 
2670         auto phys_dev = inst.GetPhysDev();
2671 
2672         PFN_vkGetPhysicalDeviceToolPropertiesEXT getToolProperties = inst.load("vkGetPhysicalDeviceToolPropertiesEXT");
2673         handle_assert_has_value(getToolProperties);
2674 
2675         uint32_t tool_count = 0;
2676         ASSERT_EQ(VK_SUCCESS, getToolProperties(phys_dev, &tool_count, nullptr));
2677         ASSERT_EQ(tool_count, 0U);
2678     }
2679     {  // extension is supported in driver
2680         FrameworkEnvironment env{};
2681         env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA))
2682             .set_supports_tooling_info_ext(true)
2683             .add_tooling_property(icd_tool_props)
2684             .add_physical_device(PhysicalDevice{}.add_extension(VK_EXT_TOOLING_INFO_EXTENSION_NAME).finish());
2685 
2686         InstWrapper inst{env.vulkan_functions};
2687         inst.CheckCreate();
2688 
2689         auto phys_dev = inst.GetPhysDev();
2690 
2691         PFN_vkGetPhysicalDeviceToolPropertiesEXT getToolProperties = inst.load("vkGetPhysicalDeviceToolPropertiesEXT");
2692         handle_assert_has_value(getToolProperties);
2693         uint32_t tool_count = 0;
2694         ASSERT_EQ(VK_SUCCESS, getToolProperties(phys_dev, &tool_count, nullptr));
2695         ASSERT_EQ(tool_count, 1U);
2696         VkPhysicalDeviceToolPropertiesEXT props{};
2697         ASSERT_EQ(VK_SUCCESS, getToolProperties(phys_dev, &tool_count, &props));
2698         ASSERT_EQ(tool_count, 1U);
2699         string_eq(props.name, icd_tool_props.name);
2700     }
2701     {  // core
2702         FrameworkEnvironment env{};
2703         env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, VK_API_VERSION_1_3))
2704             .add_physical_device({})
2705             .set_supports_tooling_info_core(true)
2706             .add_tooling_property(icd_tool_props)
2707             .physical_devices.back()
2708             .properties.apiVersion = VK_MAKE_API_VERSION(0, 1, 3, 0);
2709 
2710         InstWrapper inst{env.vulkan_functions};
2711         inst.CheckCreate();
2712 
2713         auto phys_dev = inst.GetPhysDev();
2714 
2715         PFN_vkGetPhysicalDeviceToolProperties getToolProperties = inst.load("vkGetPhysicalDeviceToolProperties");
2716         handle_assert_has_value(getToolProperties);
2717         uint32_t tool_count = 0;
2718         ASSERT_EQ(VK_SUCCESS, getToolProperties(phys_dev, &tool_count, nullptr));
2719         ASSERT_EQ(tool_count, 1U);
2720         VkPhysicalDeviceToolProperties props{};
2721         ASSERT_EQ(VK_SUCCESS, getToolProperties(phys_dev, &tool_count, &props));
2722         ASSERT_EQ(tool_count, 1U);
2723         string_eq(props.name, icd_tool_props.name);
2724     }
2725 }
TEST(CreateInstance, InstanceNullLayerPtr)2726 TEST(CreateInstance, InstanceNullLayerPtr) {
2727     FrameworkEnvironment env{};
2728     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
2729     VkInstance inst = VK_NULL_HANDLE;
2730     VkInstanceCreateInfo info{};
2731     info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
2732     info.enabledLayerCount = 1;
2733 
2734     ASSERT_EQ(env.vulkan_functions.vkCreateInstance(&info, VK_NULL_HANDLE, &inst), VK_ERROR_LAYER_NOT_PRESENT);
2735 }
TEST(CreateInstance, InstanceNullExtensionPtr)2736 TEST(CreateInstance, InstanceNullExtensionPtr) {
2737     FrameworkEnvironment env{};
2738     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
2739     VkInstance inst = VK_NULL_HANDLE;
2740     VkInstanceCreateInfo info{};
2741     info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
2742     info.enabledExtensionCount = 1;
2743 
2744     ASSERT_EQ(env.vulkan_functions.vkCreateInstance(&info, VK_NULL_HANDLE, &inst), VK_ERROR_EXTENSION_NOT_PRESENT);
2745 }
2746 
2747 #if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__GNU__)
2748 // NOTE: Sort order only affects Linux
TEST(SortedPhysicalDevices, DevicesSortEnabled10NoAppExt)2749 TEST(SortedPhysicalDevices, DevicesSortEnabled10NoAppExt) {
2750     FrameworkEnvironment env{};
2751     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
2752     env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
2753     env.get_test_icd(0).physical_devices.push_back({"pd0"});
2754     env.get_test_icd(0).physical_devices.back().set_pci_bus(7);
2755     FillInRandomDeviceProps(env.get_test_icd(0).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU,
2756                             VK_API_VERSION_1_1, 888, 0xAAA001);
2757     env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2758     env.get_test_icd(0).physical_devices.push_back({"pd1"});
2759     env.get_test_icd(0).physical_devices.back().set_pci_bus(3);
2760     FillInRandomDeviceProps(env.get_test_icd(0).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
2761                             VK_API_VERSION_1_1, 888, 0xAAA002);
2762     env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2763 
2764     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_0));
2765     env.get_test_icd(1).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
2766     env.get_test_icd(1).physical_devices.push_back({"pd2"});
2767     env.get_test_icd(1).physical_devices.back().set_pci_bus(0);
2768     FillInRandomDeviceProps(env.get_test_icd(1).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_CPU, VK_API_VERSION_1_0,
2769                             1, 0xBBBB001);
2770     env.get_test_icd(1).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2771 
2772     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
2773     env.get_test_icd(2).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
2774     env.get_test_icd(2).physical_devices.push_back({"pd3"});
2775     env.get_test_icd(2).physical_devices.back().set_pci_bus(1);
2776     FillInRandomDeviceProps(env.get_test_icd(2).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU,
2777                             VK_API_VERSION_1_1, 75, 0xCCCC001);
2778     env.get_test_icd(2).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2779     env.get_test_icd(2).physical_devices.push_back({"pd4"});
2780     env.get_test_icd(2).physical_devices.back().set_pci_bus(4);
2781     FillInRandomDeviceProps(env.get_test_icd(2).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU,
2782                             VK_API_VERSION_1_0, 75, 0xCCCC002);
2783     env.get_test_icd(2).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2784 
2785     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
2786     env.get_test_icd(3).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
2787     env.get_test_icd(3).physical_devices.push_back({"pd5"});
2788     env.get_test_icd(3).physical_devices.back().set_pci_bus(0);
2789     FillInRandomDeviceProps(env.get_test_icd(3).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU,
2790                             VK_API_VERSION_1_1, 6940, 0xDDDD001);
2791     env.get_test_icd(3).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2792 
2793     InstWrapper instance(env.vulkan_functions);
2794     instance.CheckCreate();
2795 
2796     const uint32_t max_phys_devs = 6;
2797     uint32_t device_count = max_phys_devs;
2798     std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
2799     ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
2800     ASSERT_EQ(device_count, max_phys_devs);
2801 
2802     for (uint32_t dev = 0; dev < device_count; ++dev) {
2803         VkPhysicalDeviceProperties props{};
2804         instance->vkGetPhysicalDeviceProperties(physical_devices[dev], &props);
2805 
2806         switch (dev) {
2807             case 0:
2808                 ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
2809                 ASSERT_EQ(true, !strcmp("pd3", props.deviceName));
2810                 ASSERT_EQ(props.vendorID, 75);
2811                 ASSERT_EQ(props.deviceID, 0xCCCC001);
2812                 break;
2813             case 1:
2814                 ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
2815                 ASSERT_EQ(true, !strcmp("pd4", props.deviceName));
2816                 ASSERT_EQ(props.vendorID, 75);
2817                 ASSERT_EQ(props.deviceID, 0xCCCC002);
2818                 break;
2819             case 2:
2820                 ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
2821                 ASSERT_EQ(true, !strcmp("pd0", props.deviceName));
2822                 ASSERT_EQ(props.vendorID, 888);
2823                 ASSERT_EQ(props.deviceID, 0xAAA001);
2824                 break;
2825             case 3:
2826                 ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU);
2827                 ASSERT_EQ(true, !strcmp("pd1", props.deviceName));
2828                 ASSERT_EQ(props.vendorID, 888);
2829                 ASSERT_EQ(props.deviceID, 0xAAA002);
2830                 break;
2831             case 4:
2832                 ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU);
2833                 ASSERT_EQ(true, !strcmp("pd5", props.deviceName));
2834                 ASSERT_EQ(props.vendorID, 6940U);
2835                 ASSERT_EQ(props.deviceID, 0xDDDD001);
2836                 break;
2837             case 5:
2838                 ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_CPU);
2839                 ASSERT_EQ(true, !strcmp("pd2", props.deviceName));
2840                 ASSERT_EQ(props.vendorID, 1U);
2841                 ASSERT_EQ(props.deviceID, 0xBBBB001);
2842                 break;
2843             default:
2844                 ASSERT_EQ(false, true);
2845         }
2846     }
2847 
2848     // Make sure if we call enumerate again, the information is the same
2849     std::array<VkPhysicalDevice, max_phys_devs> physical_devices_again;
2850     ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices_again.data()));
2851     ASSERT_EQ(device_count, max_phys_devs);
2852     for (uint32_t dev = 0; dev < device_count; ++dev) {
2853         ASSERT_EQ(physical_devices[dev], physical_devices_again[dev]);
2854     }
2855 }
2856 
TEST(SortedPhysicalDevices, DevicesSortEnabled10AppExt)2857 TEST(SortedPhysicalDevices, DevicesSortEnabled10AppExt) {
2858     FrameworkEnvironment env{};
2859     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
2860     env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
2861     env.get_test_icd(0).physical_devices.push_back({"pd0"});
2862     env.get_test_icd(0).physical_devices.back().set_pci_bus(7);
2863     FillInRandomDeviceProps(env.get_test_icd(0).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU,
2864                             VK_API_VERSION_1_1, 888, 0xAAA001);
2865     env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2866     env.get_test_icd(0).physical_devices.push_back({"pd1"});
2867     env.get_test_icd(0).physical_devices.back().set_pci_bus(3);
2868     FillInRandomDeviceProps(env.get_test_icd(0).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
2869                             VK_API_VERSION_1_1, 888, 0xAAA002);
2870     env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2871 
2872     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_0));
2873     env.get_test_icd(1).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
2874     env.get_test_icd(1).physical_devices.push_back({"pd2"});
2875     env.get_test_icd(1).physical_devices.back().set_pci_bus(0);
2876     FillInRandomDeviceProps(env.get_test_icd(1).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_CPU, VK_API_VERSION_1_0,
2877                             1, 0xBBBB001);
2878     env.get_test_icd(1).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2879 
2880     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
2881     env.get_test_icd(2).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
2882     env.get_test_icd(2).physical_devices.push_back({"pd3"});
2883     env.get_test_icd(2).physical_devices.back().set_pci_bus(1);
2884     FillInRandomDeviceProps(env.get_test_icd(2).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU,
2885                             VK_API_VERSION_1_1, 75, 0xCCCC001);
2886     env.get_test_icd(2).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2887     env.get_test_icd(2).physical_devices.push_back({"pd4"});
2888     env.get_test_icd(2).physical_devices.back().set_pci_bus(4);
2889     FillInRandomDeviceProps(env.get_test_icd(2).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU,
2890                             VK_API_VERSION_1_0, 75, 0xCCCC002);
2891     env.get_test_icd(2).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2892 
2893     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
2894     env.get_test_icd(3).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
2895     env.get_test_icd(3).physical_devices.push_back({"pd5"});
2896     env.get_test_icd(3).physical_devices.back().set_pci_bus(0);
2897     FillInRandomDeviceProps(env.get_test_icd(3).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU,
2898                             VK_API_VERSION_1_1, 6940, 0xDDDD001);
2899     env.get_test_icd(3).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2900 
2901     InstWrapper instance(env.vulkan_functions);
2902     instance.create_info.add_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
2903     instance.CheckCreate();
2904 
2905     PFN_vkGetPhysicalDeviceProperties2KHR GetPhysDevProps2 = instance.load("vkGetPhysicalDeviceProperties2KHR");
2906     ASSERT_NE(GetPhysDevProps2, nullptr);
2907 
2908     const uint32_t max_phys_devs = 6;
2909     uint32_t device_count = max_phys_devs;
2910     std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
2911     ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
2912     ASSERT_EQ(device_count, max_phys_devs);
2913 
2914     for (uint32_t dev = 0; dev < device_count; ++dev) {
2915         VkPhysicalDeviceProperties props{};
2916         instance->vkGetPhysicalDeviceProperties(physical_devices[dev], &props);
2917         VkPhysicalDeviceProperties2KHR props2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2};
2918         VkPhysicalDevicePCIBusInfoPropertiesEXT pci_bus_info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT};
2919         props2.pNext = &pci_bus_info;
2920         GetPhysDevProps2(physical_devices[dev], &props2);
2921 
2922         switch (dev) {
2923             case 0:
2924                 ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
2925                 ASSERT_EQ(true, !strcmp("pd3", props.deviceName));
2926                 ASSERT_EQ(props.vendorID, 75);
2927                 ASSERT_EQ(props.deviceID, 0xCCCC001);
2928                 ASSERT_EQ(pci_bus_info.pciBus, 1U);
2929                 break;
2930             case 1:
2931                 ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
2932                 ASSERT_EQ(true, !strcmp("pd4", props.deviceName));
2933                 ASSERT_EQ(props.vendorID, 75);
2934                 ASSERT_EQ(props.deviceID, 0xCCCC002);
2935                 ASSERT_EQ(pci_bus_info.pciBus, 4U);
2936                 break;
2937             case 2:
2938                 ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
2939                 ASSERT_EQ(true, !strcmp("pd0", props.deviceName));
2940                 ASSERT_EQ(props.vendorID, 888);
2941                 ASSERT_EQ(props.deviceID, 0xAAA001);
2942                 ASSERT_EQ(pci_bus_info.pciBus, 7);
2943                 break;
2944             case 3:
2945                 ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU);
2946                 ASSERT_EQ(true, !strcmp("pd1", props.deviceName));
2947                 ASSERT_EQ(props.vendorID, 888);
2948                 ASSERT_EQ(props.deviceID, 0xAAA002);
2949                 ASSERT_EQ(pci_bus_info.pciBus, 3U);
2950                 break;
2951             case 4:
2952                 ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU);
2953                 ASSERT_EQ(true, !strcmp("pd5", props.deviceName));
2954                 ASSERT_EQ(props.vendorID, 6940U);
2955                 ASSERT_EQ(props.deviceID, 0xDDDD001);
2956                 ASSERT_EQ(pci_bus_info.pciBus, 0U);
2957                 break;
2958             case 5:
2959                 ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_CPU);
2960                 ASSERT_EQ(true, !strcmp("pd2", props.deviceName));
2961                 ASSERT_EQ(props.vendorID, 1U);
2962                 ASSERT_EQ(props.deviceID, 0xBBBB001);
2963                 ASSERT_EQ(pci_bus_info.pciBus, 0U);
2964                 break;
2965             default:
2966                 ASSERT_EQ(false, true);
2967         }
2968     }
2969 
2970     // Make sure if we call enumerate again, the information is the same
2971     std::array<VkPhysicalDevice, max_phys_devs> physical_devices_again;
2972     ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices_again.data()));
2973     ASSERT_EQ(device_count, max_phys_devs);
2974     for (uint32_t dev = 0; dev < device_count; ++dev) {
2975         ASSERT_EQ(physical_devices[dev], physical_devices_again[dev]);
2976     }
2977 }
2978 
TEST(SortedPhysicalDevices, DevicesSortEnabled11)2979 TEST(SortedPhysicalDevices, DevicesSortEnabled11) {
2980     FrameworkEnvironment env{};
2981     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
2982     env.get_test_icd(0).set_icd_api_version(VK_API_VERSION_1_1);
2983     env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
2984     env.get_test_icd(0).physical_devices.push_back({"pd0"});
2985     env.get_test_icd(0).physical_devices.back().set_pci_bus(7);
2986     FillInRandomDeviceProps(env.get_test_icd(0).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU,
2987                             VK_API_VERSION_1_0, 888, 0xAAA001);
2988     env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2989     env.get_test_icd(0).physical_devices.push_back({"pd1"});
2990     env.get_test_icd(0).physical_devices.back().set_pci_bus(3);
2991     FillInRandomDeviceProps(env.get_test_icd(0).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
2992                             VK_API_VERSION_1_0, 888, 0xAAA002);
2993     env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2994 
2995     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
2996     env.get_test_icd(1).set_icd_api_version(VK_API_VERSION_1_1);
2997     env.get_test_icd(1).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
2998     env.get_test_icd(1).physical_devices.push_back({"pd2"});
2999     env.get_test_icd(1).physical_devices.back().set_pci_bus(0);
3000     FillInRandomDeviceProps(env.get_test_icd(1).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_CPU, VK_API_VERSION_1_0,
3001                             1, 0xBBBB001);
3002     env.get_test_icd(1).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3003 
3004     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
3005     env.get_test_icd(2).set_icd_api_version(VK_API_VERSION_1_1);
3006     env.get_test_icd(2).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
3007     env.get_test_icd(2).physical_devices.push_back({"pd3"});
3008     env.get_test_icd(2).physical_devices.back().set_pci_bus(1);
3009     FillInRandomDeviceProps(env.get_test_icd(2).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU,
3010                             VK_API_VERSION_1_1, 75, 0xCCCC001);
3011     env.get_test_icd(2).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3012     env.get_test_icd(2).physical_devices.push_back({"pd4"});
3013     env.get_test_icd(2).physical_devices.back().set_pci_bus(4);
3014     FillInRandomDeviceProps(env.get_test_icd(2).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU,
3015                             VK_API_VERSION_1_1, 75, 0xCCCC002);
3016     env.get_test_icd(2).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3017 
3018     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
3019     env.get_test_icd(3).set_icd_api_version(VK_API_VERSION_1_1);
3020     env.get_test_icd(3).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
3021     env.get_test_icd(3).physical_devices.push_back({"pd5"});
3022     env.get_test_icd(3).physical_devices.back().set_pci_bus(0);
3023     FillInRandomDeviceProps(env.get_test_icd(3).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU,
3024                             VK_API_VERSION_1_1, 6940, 0xDDDD001);
3025     env.get_test_icd(3).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3026 
3027     InstWrapper instance(env.vulkan_functions);
3028     instance.create_info.set_api_version(VK_API_VERSION_1_1);
3029     instance.CheckCreate();
3030 
3031     PFN_vkGetPhysicalDeviceProperties2 GetPhysDevProps2 = instance.load("vkGetPhysicalDeviceProperties2");
3032     ASSERT_NE(GetPhysDevProps2, nullptr);
3033 
3034     const uint32_t max_phys_devs = 6;
3035     uint32_t device_count = max_phys_devs;
3036     std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
3037     ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
3038     ASSERT_EQ(device_count, max_phys_devs);
3039 
3040     for (uint32_t dev = 0; dev < device_count; ++dev) {
3041         VkPhysicalDeviceProperties props{};
3042         instance->vkGetPhysicalDeviceProperties(physical_devices[dev], &props);
3043         VkPhysicalDeviceProperties2KHR props2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2};
3044         VkPhysicalDevicePCIBusInfoPropertiesEXT pci_bus_info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT};
3045         props2.pNext = &pci_bus_info;
3046         GetPhysDevProps2(physical_devices[dev], &props2);
3047 
3048         switch (dev) {
3049             case 0:
3050                 ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
3051                 ASSERT_EQ(true, !strcmp("pd3", props.deviceName));
3052                 ASSERT_EQ(props.vendorID, 75);
3053                 ASSERT_EQ(props.deviceID, 0xCCCC001);
3054                 ASSERT_EQ(pci_bus_info.pciBus, 1U);
3055                 break;
3056             case 1:
3057                 ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
3058                 ASSERT_EQ(true, !strcmp("pd4", props.deviceName));
3059                 ASSERT_EQ(props.vendorID, 75);
3060                 ASSERT_EQ(props.deviceID, 0xCCCC002);
3061                 ASSERT_EQ(pci_bus_info.pciBus, 4U);
3062                 break;
3063             case 2:
3064                 ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
3065                 ASSERT_EQ(true, !strcmp("pd0", props.deviceName));
3066                 ASSERT_EQ(props.vendorID, 888);
3067                 ASSERT_EQ(props.deviceID, 0xAAA001);
3068                 ASSERT_EQ(pci_bus_info.pciBus, 7);
3069                 break;
3070             case 3:
3071                 ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU);
3072                 ASSERT_EQ(true, !strcmp("pd1", props.deviceName));
3073                 ASSERT_EQ(props.vendorID, 888);
3074                 ASSERT_EQ(props.deviceID, 0xAAA002);
3075                 ASSERT_EQ(pci_bus_info.pciBus, 3U);
3076                 break;
3077             case 4:
3078                 ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU);
3079                 ASSERT_EQ(true, !strcmp("pd5", props.deviceName));
3080                 ASSERT_EQ(props.vendorID, 6940U);
3081                 ASSERT_EQ(props.deviceID, 0xDDDD001);
3082                 ASSERT_EQ(pci_bus_info.pciBus, 0U);
3083                 break;
3084             case 5:
3085                 ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_CPU);
3086                 ASSERT_EQ(true, !strcmp("pd2", props.deviceName));
3087                 ASSERT_EQ(props.vendorID, 1U);
3088                 ASSERT_EQ(props.deviceID, 0xBBBB001);
3089                 ASSERT_EQ(pci_bus_info.pciBus, 0U);
3090                 break;
3091             default:
3092                 ASSERT_EQ(false, true);
3093         }
3094     }
3095 
3096     // Make sure if we call enumerate again, the information is the same
3097     std::array<VkPhysicalDevice, max_phys_devs> physical_devices_again;
3098     ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices_again.data()));
3099     ASSERT_EQ(device_count, max_phys_devs);
3100     for (uint32_t dev = 0; dev < device_count; ++dev) {
3101         ASSERT_EQ(physical_devices[dev], physical_devices_again[dev]);
3102     }
3103 }
3104 
TEST(SortedPhysicalDevices, DevicesSortedDisabled)3105 TEST(SortedPhysicalDevices, DevicesSortedDisabled) {
3106     FrameworkEnvironment env{};
3107 
3108     EnvVarWrapper disable_select_env_var{"VK_LOADER_DISABLE_SELECT", "1"};
3109 
3110     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_0));
3111     env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
3112     env.get_test_icd(0).physical_devices.push_back({"pd0"});
3113     FillInRandomDeviceProps(env.get_test_icd(0).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU,
3114                             VK_API_VERSION_1_0, 888, 0xAAA001);
3115     env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3116     env.get_test_icd(0).physical_devices.push_back({"pd1"});
3117     FillInRandomDeviceProps(env.get_test_icd(0).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
3118                             VK_API_VERSION_1_0, 888, 0xAAA002);
3119     env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3120 
3121     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_0));
3122     env.get_test_icd(1).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
3123     env.get_test_icd(1).physical_devices.push_back({"pd2"});
3124     FillInRandomDeviceProps(env.get_test_icd(1).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_CPU, VK_API_VERSION_1_0,
3125                             1, 0xBBBB001);
3126     env.get_test_icd(1).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3127 
3128     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_0));
3129     env.get_test_icd(2).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
3130     env.get_test_icd(2).physical_devices.push_back({"pd3"});
3131     FillInRandomDeviceProps(env.get_test_icd(2).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU,
3132                             VK_API_VERSION_1_0, 75, 0xCCCC001);
3133     env.get_test_icd(2).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3134     env.get_test_icd(2).physical_devices.push_back({"pd4"});
3135     FillInRandomDeviceProps(env.get_test_icd(2).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU,
3136                             VK_API_VERSION_1_0, 75, 0xCCCC002);
3137     env.get_test_icd(2).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3138 
3139     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_0));
3140     env.get_test_icd(3).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
3141     env.get_test_icd(3).physical_devices.push_back({"pd5"});
3142     FillInRandomDeviceProps(env.get_test_icd(3).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU,
3143                             VK_API_VERSION_1_0, 6940, 0xDDDD001);
3144     env.get_test_icd(3).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3145 
3146     InstWrapper instance(env.vulkan_functions);
3147     instance.create_info.add_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
3148     instance.CheckCreate();
3149 
3150     // Just make sure we have the correct number of devices
3151     const uint32_t max_phys_devs = 6;
3152     uint32_t device_count = max_phys_devs;
3153     std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
3154     ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
3155     ASSERT_EQ(device_count, max_phys_devs);
3156 
3157     // Make sure the devices are not in the sorted order.  The order is really undefined, but the chances of
3158     // it being exactly the expected sorted is very low.
3159     bool sorted = true;
3160     for (uint32_t dev = 0; dev < device_count; ++dev) {
3161         VkPhysicalDeviceProperties props{};
3162         instance->vkGetPhysicalDeviceProperties(physical_devices[dev], &props);
3163 
3164         switch (dev) {
3165             case 0:
3166                 if (props.deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU || strcmp("pd4", props.deviceName)) {
3167                     sorted = false;
3168                 }
3169                 break;
3170             case 1:
3171                 if (props.deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU || strcmp("pd0", props.deviceName)) {
3172                     sorted = false;
3173                 }
3174                 break;
3175             case 2:
3176                 if (props.deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU || strcmp("pd3", props.deviceName)) {
3177                     sorted = false;
3178                 }
3179                 break;
3180             case 3:
3181                 if (props.deviceType != VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU || strcmp("pd1", props.deviceName)) {
3182                     sorted = false;
3183                 }
3184                 break;
3185             case 4:
3186                 if (props.deviceType != VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU || strcmp("pd5", props.deviceName)) {
3187                     sorted = false;
3188                 }
3189                 break;
3190             case 5:
3191                 if (props.deviceType != VK_PHYSICAL_DEVICE_TYPE_CPU || strcmp("pd2", props.deviceName)) {
3192                     sorted = false;
3193                 }
3194                 break;
3195             default:
3196                 ASSERT_EQ(false, true);
3197         }
3198         if (!sorted) {
3199             break;
3200         }
3201     }
3202     ASSERT_EQ(false, sorted);
3203 
3204     // Make sure if we call enumerate again, the information is the same
3205     std::array<VkPhysicalDevice, max_phys_devs> physical_devices_again;
3206     ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices_again.data()));
3207     ASSERT_EQ(device_count, max_phys_devs);
3208     for (uint32_t dev = 0; dev < device_count; ++dev) {
3209         ASSERT_EQ(physical_devices[dev], physical_devices_again[dev]);
3210     }
3211 }
3212 
TEST(SortedPhysicalDevices, DeviceGroupsSortedEnabled)3213 TEST(SortedPhysicalDevices, DeviceGroupsSortedEnabled) {
3214     FrameworkEnvironment env{};
3215 
3216     // ICD 0: Vulkan 1.1
3217     //   PhysDev 0: pd0, Discrete, Vulkan 1.1, Bus 7
3218     //   PhysDev 1: pd1, Integrated, Vulkan 1.1, Bus 3
3219     //   PhysDev 2: pd2, Discrete, Vulkan 1.1, Bus 6
3220     //   Group 0: PhysDev 0, PhysDev 2
3221     //   Group 1: PhysDev 1
3222     // ICD 1: Vulkan 1.1
3223     //   PhysDev 3: pd3, CPU, Vulkan 1.1, Bus 0
3224     // ICD 2: Vulkan 1.1
3225     //   PhysDev 4: pd4, Discrete, Vulkan 1.1, Bus 1
3226     //   PhysDev 5: pd5, Discrete, Vulkan 1.1, Bus 4
3227     //   PhysDev 6: pd6, Discrete, Vulkan 1.1, Bus 2
3228     //   Group 0: PhysDev 5, PhysDev 6
3229     //   Group 1: PhysDev 4
3230     // ICD 3: Vulkan 1.1
3231     //   PhysDev 7: pd7, Virtual, Vulkan 1.1, Bus 0
3232     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
3233     auto& cur_icd_0 = env.get_test_icd(0);
3234     cur_icd_0.set_icd_api_version(VK_API_VERSION_1_1);
3235     cur_icd_0.physical_devices.push_back({"pd0"});
3236     cur_icd_0.physical_devices.back().set_pci_bus(7);
3237     cur_icd_0.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3238     FillInRandomDeviceProps(cur_icd_0.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_API_VERSION_1_1,
3239                             888, 0xAAA001);
3240     cur_icd_0.physical_devices.push_back({"pd1"});
3241     cur_icd_0.physical_devices.back().set_pci_bus(3);
3242     cur_icd_0.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3243     FillInRandomDeviceProps(cur_icd_0.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
3244                             VK_API_VERSION_1_1, 888, 0xAAA002);
3245     cur_icd_0.physical_devices.push_back({"pd2"});
3246     cur_icd_0.physical_devices.back().set_pci_bus(6);
3247     cur_icd_0.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3248     FillInRandomDeviceProps(cur_icd_0.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_API_VERSION_1_1,
3249                             888, 0xAAA003);
3250     cur_icd_0.physical_device_groups.push_back({});
3251     cur_icd_0.physical_device_groups.back()
3252         .use_physical_device(cur_icd_0.physical_devices[0])
3253         .use_physical_device(cur_icd_0.physical_devices[2]);
3254     cur_icd_0.physical_device_groups.push_back({cur_icd_0.physical_devices[1]});
3255 
3256     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
3257     auto& cur_icd_1 = env.get_test_icd(1);
3258     cur_icd_1.set_icd_api_version(VK_API_VERSION_1_1);
3259     cur_icd_1.physical_devices.push_back({"pd3"});
3260     cur_icd_1.physical_devices.back().set_pci_bus(0);
3261     cur_icd_1.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3262     FillInRandomDeviceProps(cur_icd_1.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_CPU, VK_API_VERSION_1_1, 1,
3263                             0xBBBB001);
3264 
3265     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
3266     auto& cur_icd_2 = env.get_test_icd(2);
3267     cur_icd_2.set_icd_api_version(VK_API_VERSION_1_1);
3268     cur_icd_2.physical_devices.push_back({"pd4"});
3269     cur_icd_2.physical_devices.back().set_pci_bus(1);
3270     cur_icd_2.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3271     FillInRandomDeviceProps(cur_icd_2.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_API_VERSION_1_1,
3272                             75, 0xCCCC001);
3273     cur_icd_2.physical_devices.push_back({"pd5"});
3274     cur_icd_2.physical_devices.back().set_pci_bus(4);
3275     cur_icd_2.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3276     FillInRandomDeviceProps(cur_icd_2.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_API_VERSION_1_1,
3277                             75, 0xCCCC002);
3278     cur_icd_2.physical_devices.push_back({"pd6"});
3279     cur_icd_2.physical_devices.back().set_pci_bus(2);
3280     cur_icd_2.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3281     FillInRandomDeviceProps(cur_icd_2.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_API_VERSION_1_1,
3282                             75, 0xCCCC003);
3283     cur_icd_2.physical_device_groups.push_back({});
3284     cur_icd_2.physical_device_groups.back()
3285         .use_physical_device(cur_icd_2.physical_devices[1])
3286         .use_physical_device(cur_icd_2.physical_devices[2]);
3287     cur_icd_2.physical_device_groups.push_back({cur_icd_2.physical_devices[0]});
3288 
3289     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
3290     auto& cur_icd_3 = env.get_test_icd(3);
3291     cur_icd_3.set_icd_api_version(VK_API_VERSION_1_1);
3292     cur_icd_3.physical_devices.push_back({"pd7"});
3293     cur_icd_3.physical_devices.back().set_pci_bus(0);
3294     cur_icd_3.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3295     FillInRandomDeviceProps(cur_icd_3.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU, VK_API_VERSION_1_1,
3296                             6940, 0xDDDD001);
3297 
3298     InstWrapper inst(env.vulkan_functions);
3299     inst.create_info.set_api_version(VK_API_VERSION_1_1);
3300     inst.CheckCreate();
3301 
3302     PFN_vkGetPhysicalDeviceProperties2 GetPhysDevProps2 = inst.load("vkGetPhysicalDeviceProperties2");
3303     ASSERT_NE(GetPhysDevProps2, nullptr);
3304 
3305     const uint32_t max_phys_devs = 8;
3306     uint32_t device_count = max_phys_devs;
3307     std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
3308     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &device_count, physical_devices.data()));
3309     ASSERT_EQ(device_count, max_phys_devs);
3310 
3311     const uint32_t max_phys_dev_groups = 6;
3312     uint32_t group_count = max_phys_dev_groups;
3313     std::array<VkPhysicalDeviceGroupProperties, max_phys_dev_groups> physical_device_groups{};
3314     for (auto& group : physical_device_groups) group.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES;
3315     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &group_count, physical_device_groups.data()));
3316     ASSERT_EQ(group_count, max_phys_dev_groups);
3317 
3318     uint32_t cur_dev = 0;
3319     for (uint32_t group = 0; group < max_phys_dev_groups; ++group) {
3320         for (uint32_t dev = 0; dev < physical_device_groups[group].physicalDeviceCount; ++dev) {
3321             VkPhysicalDeviceProperties props{};
3322             inst->vkGetPhysicalDeviceProperties(physical_device_groups[group].physicalDevices[dev], &props);
3323             VkPhysicalDeviceProperties2 props2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2};
3324             VkPhysicalDevicePCIBusInfoPropertiesEXT pci_bus_info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT};
3325             props2.pNext = &pci_bus_info;
3326             GetPhysDevProps2(physical_device_groups[group].physicalDevices[dev], &props2);
3327             switch (cur_dev++) {
3328                 case 0:
3329                     ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
3330                     ASSERT_EQ(true, !strcmp("pd4", props.deviceName));
3331                     ASSERT_EQ(props.vendorID, 75);
3332                     ASSERT_EQ(props.deviceID, 0xCCCC001);
3333                     ASSERT_EQ(pci_bus_info.pciBus, 1U);
3334                     break;
3335                 case 1:
3336                     ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
3337                     ASSERT_EQ(true, !strcmp("pd6", props.deviceName));
3338                     ASSERT_EQ(props.vendorID, 75);
3339                     ASSERT_EQ(props.deviceID, 0xCCCC003);
3340                     ASSERT_EQ(pci_bus_info.pciBus, 2U);
3341                     break;
3342                 case 2:
3343                     ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
3344                     ASSERT_EQ(true, !strcmp("pd5", props.deviceName));
3345                     ASSERT_EQ(props.vendorID, 75);
3346                     ASSERT_EQ(props.deviceID, 0xCCCC002);
3347                     ASSERT_EQ(pci_bus_info.pciBus, 4U);
3348                     break;
3349                 case 3:
3350                     ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
3351                     ASSERT_EQ(true, !strcmp("pd2", props.deviceName));
3352                     ASSERT_EQ(props.vendorID, 888);
3353                     ASSERT_EQ(props.deviceID, 0xAAA003);
3354                     ASSERT_EQ(pci_bus_info.pciBus, 6);
3355                     break;
3356                 case 4:
3357                     ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
3358                     ASSERT_EQ(true, !strcmp("pd0", props.deviceName));
3359                     ASSERT_EQ(props.vendorID, 888);
3360                     ASSERT_EQ(props.deviceID, 0xAAA001);
3361                     ASSERT_EQ(pci_bus_info.pciBus, 7);
3362                     break;
3363                 case 5:
3364                     ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU);
3365                     ASSERT_EQ(true, !strcmp("pd1", props.deviceName));
3366                     ASSERT_EQ(props.vendorID, 888);
3367                     ASSERT_EQ(props.deviceID, 0xAAA002);
3368                     ASSERT_EQ(pci_bus_info.pciBus, 3U);
3369                     break;
3370                 case 6:
3371                     ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU);
3372                     ASSERT_EQ(true, !strcmp("pd7", props.deviceName));
3373                     ASSERT_EQ(props.vendorID, 6940U);
3374                     ASSERT_EQ(props.deviceID, 0xDDDD001);
3375                     ASSERT_EQ(pci_bus_info.pciBus, 0U);
3376                     break;
3377                 case 7:
3378                     ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_CPU);
3379                     ASSERT_EQ(true, !strcmp("pd3", props.deviceName));
3380                     ASSERT_EQ(props.vendorID, 1U);
3381                     ASSERT_EQ(props.deviceID, 0xBBBB001);
3382                     ASSERT_EQ(pci_bus_info.pciBus, 0U);
3383                     break;
3384                 default:
3385                     ASSERT_EQ(false, true);
3386             }
3387         }
3388     }
3389 
3390     // Make sure if we call enumerate again, the information is the same
3391     std::array<VkPhysicalDeviceGroupProperties, max_phys_dev_groups> physical_device_groups_again{};
3392     for (auto& group : physical_device_groups_again) group.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES;
3393 
3394     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &group_count, physical_device_groups_again.data()));
3395     ASSERT_EQ(group_count, max_phys_dev_groups);
3396     for (uint32_t group = 0; group < max_phys_dev_groups; ++group) {
3397         ASSERT_EQ(physical_device_groups[group].physicalDeviceCount, physical_device_groups_again[group].physicalDeviceCount);
3398         for (uint32_t dev = 0; dev < physical_device_groups[group].physicalDeviceCount; ++dev) {
3399             ASSERT_EQ(physical_device_groups[group].physicalDevices[dev], physical_device_groups_again[group].physicalDevices[dev]);
3400         }
3401     }
3402 }
3403 
TEST(SortedPhysicalDevices, DeviceGroupsSortedDisabled)3404 TEST(SortedPhysicalDevices, DeviceGroupsSortedDisabled) {
3405     FrameworkEnvironment env{};
3406 
3407     EnvVarWrapper disable_select_env_var{"VK_LOADER_DISABLE_SELECT", "1"};
3408 
3409     // ICD 0: Vulkan 1.1
3410     //   PhysDev 0: pd0, Discrete, Vulkan 1.1, Bus 7
3411     //   PhysDev 1: pd1, Integrated, Vulkan 1.1, Bus 3
3412     //   PhysDev 2: pd2, Discrete, Vulkan 1.1, Bus 6
3413     //   Group 0: PhysDev 0, PhysDev 2
3414     //   Group 1: PhysDev 1
3415     // ICD 1: Vulkan 1.1
3416     //   PhysDev 3: pd3, CPU, Vulkan 1.1, Bus 0
3417     // ICD 2: Vulkan 1.1
3418     //   PhysDev 4: pd4, Discrete, Vulkan 1.1, Bus 1
3419     //   PhysDev 5: pd5, Discrete, Vulkan 1.1, Bus 4
3420     //   PhysDev 6: pd6, Discrete, Vulkan 1.1, Bus 2
3421     //   Group 0: PhysDev 5, PhysDev 6
3422     //   Group 1: PhysDev 4
3423     // ICD 3: Vulkan 1.1
3424     //   PhysDev 7: pd7, Virtual, Vulkan 1.1, Bus 0
3425     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
3426     auto& cur_icd_0 = env.get_test_icd(0);
3427     cur_icd_0.set_icd_api_version(VK_API_VERSION_1_1);
3428     cur_icd_0.physical_devices.push_back({"pd0"});
3429     cur_icd_0.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3430     FillInRandomDeviceProps(cur_icd_0.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_API_VERSION_1_1,
3431                             888, 0xAAA001);
3432     cur_icd_0.physical_devices.push_back({"pd1"});
3433     cur_icd_0.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3434     FillInRandomDeviceProps(cur_icd_0.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
3435                             VK_API_VERSION_1_1, 888, 0xAAA002);
3436     cur_icd_0.physical_devices.push_back({"pd2"});
3437     cur_icd_0.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3438     FillInRandomDeviceProps(cur_icd_0.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_API_VERSION_1_1,
3439                             888, 0xAAA003);
3440     cur_icd_0.physical_device_groups.push_back({});
3441     cur_icd_0.physical_device_groups.back()
3442         .use_physical_device(cur_icd_0.physical_devices[0])
3443         .use_physical_device(cur_icd_0.physical_devices[2]);
3444     cur_icd_0.physical_device_groups.push_back({cur_icd_0.physical_devices[1]});
3445 
3446     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
3447     auto& cur_icd_1 = env.get_test_icd(1);
3448     cur_icd_1.set_icd_api_version(VK_API_VERSION_1_1);
3449     cur_icd_1.physical_devices.push_back({"pd3"});
3450     cur_icd_1.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3451     FillInRandomDeviceProps(cur_icd_1.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_CPU, VK_API_VERSION_1_1, 1,
3452                             0xBBBB001);
3453 
3454     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
3455     auto& cur_icd_2 = env.get_test_icd(2);
3456     cur_icd_2.set_icd_api_version(VK_API_VERSION_1_1);
3457     cur_icd_2.physical_devices.push_back({"pd4"});
3458     cur_icd_2.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3459     FillInRandomDeviceProps(cur_icd_2.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_API_VERSION_1_1,
3460                             75, 0xCCCC001);
3461     cur_icd_2.physical_devices.push_back({"pd5"});
3462     cur_icd_2.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3463     FillInRandomDeviceProps(cur_icd_2.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_API_VERSION_1_1,
3464                             75, 0xCCCC002);
3465     cur_icd_2.physical_devices.push_back({"pd6"});
3466     cur_icd_2.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3467     FillInRandomDeviceProps(cur_icd_2.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_API_VERSION_1_1,
3468                             75, 0xCCCC003);
3469     cur_icd_2.physical_device_groups.push_back({});
3470     cur_icd_2.physical_device_groups.back()
3471         .use_physical_device(cur_icd_2.physical_devices[1])
3472         .use_physical_device(cur_icd_2.physical_devices[2]);
3473     cur_icd_2.physical_device_groups.push_back({cur_icd_2.physical_devices[0]});
3474 
3475     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
3476     auto& cur_icd_3 = env.get_test_icd(3);
3477     cur_icd_3.set_icd_api_version(VK_API_VERSION_1_1);
3478     cur_icd_3.physical_devices.push_back({"pd7"});
3479     cur_icd_3.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3480     FillInRandomDeviceProps(cur_icd_3.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU, VK_API_VERSION_1_1,
3481                             6940, 0xDDDD001);
3482 
3483     InstWrapper inst(env.vulkan_functions);
3484     inst.create_info.set_api_version(VK_API_VERSION_1_1);
3485     inst.CheckCreate();
3486 
3487     PFN_vkGetPhysicalDeviceProperties2 GetPhysDevProps2 = inst.load("vkGetPhysicalDeviceProperties2");
3488     ASSERT_NE(GetPhysDevProps2, nullptr);
3489 
3490     const uint32_t max_phys_devs = 8;
3491     uint32_t device_count = max_phys_devs;
3492     std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
3493     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &device_count, physical_devices.data()));
3494     ASSERT_EQ(device_count, max_phys_devs);
3495 
3496     const uint32_t max_phys_dev_groups = 6;
3497     uint32_t group_count = max_phys_dev_groups;
3498     std::array<VkPhysicalDeviceGroupProperties, max_phys_dev_groups> physical_device_groups{};
3499     for (auto& group : physical_device_groups) group.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES;
3500 
3501     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &group_count, physical_device_groups.data()));
3502     ASSERT_EQ(group_count, max_phys_dev_groups);
3503 
3504     // Make sure the devices are not in the sorted order.  The order is really undefined, but the chances of
3505     // it being exactly the expected sorted is very low.
3506     bool sorted = true;
3507     uint32_t cur_dev = 0;
3508     for (uint32_t group = 0; group < max_phys_dev_groups; ++group) {
3509         for (uint32_t dev = 0; dev < physical_device_groups[group].physicalDeviceCount; ++dev) {
3510             VkPhysicalDeviceProperties props{};
3511             inst->vkGetPhysicalDeviceProperties(physical_device_groups[group].physicalDevices[dev], &props);
3512             switch (cur_dev++) {
3513                 case 0:
3514                     if (props.deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU || strcmp("pd4", props.deviceName)) {
3515                         sorted = false;
3516                     }
3517                     break;
3518                 case 1:
3519                     if (props.deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU || strcmp("pd6", props.deviceName)) {
3520                         sorted = false;
3521                     }
3522                     break;
3523                 case 2:
3524                     if (props.deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU || strcmp("pd5", props.deviceName)) {
3525                         sorted = false;
3526                     }
3527                     break;
3528                 case 3:
3529                     if (props.deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU || strcmp("pd2", props.deviceName)) {
3530                         sorted = false;
3531                     }
3532                     break;
3533                 case 4:
3534                     if (props.deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU || strcmp("pd0", props.deviceName)) {
3535                         sorted = false;
3536                     }
3537                     break;
3538                 case 5:
3539                     if (props.deviceType != VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU || strcmp("pd1", props.deviceName)) {
3540                         sorted = false;
3541                     }
3542                     break;
3543                 case 6:
3544                     if (props.deviceType != VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU || strcmp("pd7", props.deviceName)) {
3545                         sorted = false;
3546                     }
3547                     break;
3548                 case 7:
3549                     if (props.deviceType != VK_PHYSICAL_DEVICE_TYPE_CPU || strcmp("pd3", props.deviceName)) {
3550                         sorted = false;
3551                     }
3552                     break;
3553                 default:
3554                     ASSERT_EQ(false, true);
3555             }
3556         }
3557         if (!sorted) {
3558             break;
3559         }
3560     }
3561     ASSERT_EQ(false, sorted);
3562 
3563     // Make sure if we call enumerate again, the information is the same
3564     std::array<VkPhysicalDeviceGroupProperties, max_phys_dev_groups> physical_device_groups_again{};
3565     for (auto& group : physical_device_groups_again) group.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES;
3566 
3567     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &group_count, physical_device_groups_again.data()));
3568     ASSERT_EQ(group_count, max_phys_dev_groups);
3569     for (uint32_t group = 0; group < max_phys_dev_groups; ++group) {
3570         ASSERT_EQ(physical_device_groups[group].physicalDeviceCount, physical_device_groups_again[group].physicalDeviceCount);
3571         for (uint32_t dev = 0; dev < physical_device_groups[group].physicalDeviceCount; ++dev) {
3572             ASSERT_EQ(physical_device_groups[group].physicalDevices[dev], physical_device_groups_again[group].physicalDevices[dev]);
3573         }
3574     }
3575 }
3576 
3577 #endif  // __linux__ || __FreeBSD__ || __OpenBSD__ || __GNU__
3578 
3579 const char* portability_driver_warning =
3580     "vkCreateInstance: Found drivers that contain devices which support the portability subset, but "
3581     "the instance does not enumerate portability drivers! Applications that wish to enumerate portability "
3582     "drivers must set the VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR bit in the VkInstanceCreateInfo "
3583     "flags and enable the VK_KHR_portability_enumeration instance extension.";
3584 
3585 const char* portability_flag_missing =
3586     "vkCreateInstance: Found drivers that contain devices which support the portability subset, but "
3587     "the instance does not enumerate portability drivers! Applications that wish to enumerate portability "
3588     "drivers must set the VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR bit in the VkInstanceCreateInfo "
3589     "flags.";
3590 
3591 const char* portability_extension_missing =
3592     "VkInstanceCreateInfo: If flags has the VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR bit set, the "
3593     "list of enabled extensions in ppEnabledExtensionNames must contain VK_KHR_portability_enumeration "
3594     "[VUID-VkInstanceCreateInfo-flags-06559 ]"
3595     "Applications that wish to enumerate portability drivers must enable the VK_KHR_portability_enumeration "
3596     "instance extension.";
3597 
TEST(PortabilityICDConfiguration, PortabilityICDOnly)3598 TEST(PortabilityICDConfiguration, PortabilityICDOnly) {
3599     FrameworkEnvironment env{};
3600     env.add_icd(
3601            TestICDDetails(ManifestICD{}.set_lib_path(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_is_portability_driver(true)))
3602         .add_physical_device("physical_device_0")
3603         .set_max_icd_interface_version(1);
3604     {  // enable portability extension and flag
3605         InstWrapper inst{env.vulkan_functions};
3606         inst.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
3607         inst.create_info.add_extension("VK_KHR_portability_enumeration");
3608         inst.create_info.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
3609         FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
3610         inst.CheckCreate();
3611         ASSERT_FALSE(env.debug_log.find(portability_driver_warning));
3612 
3613         DebugUtilsWrapper log{inst, VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
3614         CreateDebugUtilsMessenger(log);
3615 
3616         auto phys_dev = inst.GetPhysDev();
3617         handle_assert_has_value(phys_dev);
3618 
3619         DeviceWrapper dev_info{inst};
3620         dev_info.CheckCreate(phys_dev);
3621         ASSERT_FALSE(log.find(portability_driver_warning));
3622         ASSERT_FALSE(log.find(portability_flag_missing));
3623         ASSERT_FALSE(log.find(portability_extension_missing));
3624     }
3625     {  // enable portability flag but not extension - shouldn't be able to create an instance when filtering is enabled
3626         InstWrapper inst{env.vulkan_functions};
3627         inst.create_info.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
3628         inst.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
3629         FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
3630         inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER);
3631         ASSERT_TRUE(env.debug_log.find(portability_extension_missing));
3632     }
3633     {  // enable portability extension but not flag - shouldn't be able to create an instance when filtering is enabled
3634         InstWrapper inst{env.vulkan_functions};
3635         inst.create_info.add_extension("VK_KHR_portability_enumeration");
3636         inst.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
3637         FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
3638         inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER);
3639         ASSERT_TRUE(env.debug_log.find(portability_flag_missing));
3640     }
3641     {  // enable neither the portability extension or the flag - shouldn't be able to create an instance when filtering is enabled
3642         InstWrapper inst{env.vulkan_functions};
3643         inst.create_info.flags = 0;  // make sure its 0 - no portability
3644         inst.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
3645         FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
3646         inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER);
3647         ASSERT_TRUE(env.debug_log.find(portability_driver_warning));
3648     }
3649 }
3650 
TEST(PortabilityICDConfiguration, PortabilityAndRegularICD)3651 TEST(PortabilityICDConfiguration, PortabilityAndRegularICD) {
3652     FrameworkEnvironment env{};
3653     env.add_icd(TestICDDetails(ManifestICD{}.set_lib_path(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)));
3654     env.add_icd(
3655         TestICDDetails(ManifestICD{}.set_lib_path(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_is_portability_driver(true)));
3656 
3657     auto& driver0 = env.get_test_icd(0);
3658     auto& driver1 = env.get_test_icd(1);
3659 
3660     driver0.physical_devices.emplace_back("physical_device_0");
3661     driver0.max_icd_interface_version = 1;
3662 
3663     driver1.physical_devices.emplace_back("portability_physical_device_1");
3664     driver1.max_icd_interface_version = 1;
3665     {  // enable portability extension and flag
3666         InstWrapper inst{env.vulkan_functions};
3667         inst.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
3668         inst.create_info.add_extension("VK_KHR_portability_enumeration");
3669         inst.create_info.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
3670         FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
3671         inst.CheckCreate();
3672         ASSERT_FALSE(env.debug_log.find(portability_driver_warning));
3673 
3674         DebugUtilsWrapper log{inst, VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
3675         CreateDebugUtilsMessenger(log);
3676 
3677         auto phys_devs = inst.GetPhysDevs(2);
3678         for (const auto& phys_dev : phys_devs) {
3679             handle_assert_has_value(phys_dev);
3680         }
3681         DeviceWrapper dev_info_0{inst};
3682         DeviceWrapper dev_info_1{inst};
3683         dev_info_0.CheckCreate(phys_devs[0]);
3684         dev_info_1.CheckCreate(phys_devs[1]);
3685     }
3686     {  // enable portability extension but not flag - should only enumerate 1 physical device when filtering is enabled
3687         InstWrapper inst{env.vulkan_functions};
3688         inst.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
3689         inst.create_info.add_extension("VK_KHR_portability_enumeration");
3690         FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
3691         inst.CheckCreate();
3692         ASSERT_FALSE(env.debug_log.find(portability_driver_warning));
3693 
3694         DebugUtilsWrapper log{inst, VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
3695         CreateDebugUtilsMessenger(log);
3696         auto phys_dev = inst.GetPhysDev();
3697         handle_assert_has_value(phys_dev);
3698         DeviceWrapper dev_info_0{inst};
3699         dev_info_0.CheckCreate(phys_dev);
3700     }
3701     {  // enable portability flag but not extension - should only enumerate 1 physical device when filtering is enabled
3702         InstWrapper inst{env.vulkan_functions};
3703         inst.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
3704         inst.create_info.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
3705         FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
3706         inst.CheckCreate();
3707         ASSERT_FALSE(env.debug_log.find(portability_driver_warning));
3708 
3709         DebugUtilsWrapper log{inst, VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
3710         CreateDebugUtilsMessenger(log);
3711         auto phys_dev = inst.GetPhysDev();
3712         handle_assert_has_value(phys_dev);
3713         DeviceWrapper dev_info_0{inst};
3714         dev_info_0.CheckCreate(phys_dev);
3715     }
3716     {  // do not enable portability extension or flag - should only enumerate 1 physical device when filtering is enabled
3717         InstWrapper inst{env.vulkan_functions};
3718         inst.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
3719         FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
3720         inst.CheckCreate();
3721         ASSERT_FALSE(env.debug_log.find(portability_driver_warning));
3722 
3723         DebugUtilsWrapper log{inst, VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
3724         CreateDebugUtilsMessenger(log);
3725         auto phys_dev = inst.GetPhysDev();
3726         handle_assert_has_value(phys_dev);
3727         DeviceWrapper dev_info_0{inst};
3728         dev_info_0.CheckCreate(phys_dev);
3729     }
3730 }
3731 
3732 // Check that the portability enumeration flag bit doesn't get passed down
TEST(PortabilityICDConfiguration, PortabilityAndRegularICDCheckFlagsPassedIntoICD)3733 TEST(PortabilityICDConfiguration, PortabilityAndRegularICDCheckFlagsPassedIntoICD) {
3734     FrameworkEnvironment env{};
3735     env.add_icd(TestICDDetails(ManifestICD{}.set_lib_path(TEST_ICD_PATH_VERSION_2)));
3736     env.add_icd(TestICDDetails(ManifestICD{}.set_lib_path(TEST_ICD_PATH_VERSION_2).set_is_portability_driver(true)));
3737 
3738     auto& driver0 = env.get_test_icd(0);
3739     auto& driver1 = env.get_test_icd(1);
3740 
3741     driver0.physical_devices.emplace_back("physical_device_0");
3742     driver0.max_icd_interface_version = 1;
3743 
3744     driver1.physical_devices.emplace_back("portability_physical_device_1");
3745     driver1.add_instance_extension("VK_KHR_portability_enumeration");
3746     driver1.max_icd_interface_version = 1;
3747 
3748     InstWrapper inst{env.vulkan_functions};
3749     inst.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
3750     inst.create_info.add_extension("VK_KHR_portability_enumeration");
3751     inst.create_info.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR | 4;
3752 
3753     FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
3754     inst.CheckCreate();
3755     ASSERT_FALSE(env.debug_log.find(portability_driver_warning));
3756 
3757     ASSERT_EQ(static_cast<VkInstanceCreateFlags>(4), driver0.passed_in_instance_create_flags);
3758     ASSERT_EQ(VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR | static_cast<VkInstanceCreateFlags>(4),
3759               driver1.passed_in_instance_create_flags);
3760 }
3761 
TEST(PortabilityICDConfiguration, PortabilityAndRegularICDPreInstanceFunctions)3762 TEST(PortabilityICDConfiguration, PortabilityAndRegularICDPreInstanceFunctions) {
3763     FrameworkEnvironment env{};
3764     Extension first_ext{"VK_EXT_validation_features"};  // known instance extensions
3765     Extension second_ext{"VK_EXT_headless_surface"};
3766     env.add_icd(TestICDDetails(ManifestICD{}.set_lib_path(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)))
3767         .add_physical_device("physical_device_0")
3768         .set_max_icd_interface_version(1)
3769         .add_instance_extensions({first_ext, second_ext});
3770     env.add_icd(
3771            TestICDDetails(ManifestICD{}.set_lib_path(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_is_portability_driver(true)))
3772         .add_physical_device("portability_physical_device_1")
3773         .set_max_icd_interface_version(1);
3774     {
3775         // check that enumerating instance extensions work with a portability driver present
3776         auto extensions = env.GetInstanceExtensions(6);
3777         EXPECT_TRUE(string_eq(extensions.at(0).extensionName, first_ext.extensionName.c_str()));
3778         EXPECT_TRUE(string_eq(extensions.at(1).extensionName, second_ext.extensionName.c_str()));
3779         EXPECT_TRUE(string_eq(extensions.at(2).extensionName, VK_EXT_DEBUG_REPORT_EXTENSION_NAME));
3780         EXPECT_TRUE(string_eq(extensions.at(3).extensionName, VK_EXT_DEBUG_UTILS_EXTENSION_NAME));
3781         EXPECT_TRUE(string_eq(extensions.at(4).extensionName, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME));
3782         EXPECT_TRUE(string_eq(extensions.at(5).extensionName, VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME));
3783     }
3784 
3785     const char* layer_name = "TestLayer";
3786     env.add_explicit_layer(
3787         ManifestLayer{}.add_layer(
3788             ManifestLayer::LayerDescription{}.set_name(layer_name).set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)),
3789         "test_layer.json");
3790 
3791     InstWrapper inst{env.vulkan_functions};
3792     inst.create_info.add_layer(layer_name);
3793     inst.CheckCreate();
3794 
3795     VkPhysicalDevice phys_dev = inst.GetPhysDev();
3796     {  // LayersMatch
3797         auto layer_props = inst.GetActiveLayers(phys_dev, 1);
3798         ASSERT_TRUE(string_eq(layer_props.at(0).layerName, layer_name));
3799     }
3800     {  // Property count less than available
3801         VkLayerProperties layer_props;
3802         uint32_t layer_count = 0;
3803         ASSERT_EQ(VK_INCOMPLETE, env.vulkan_functions.vkEnumerateDeviceLayerProperties(phys_dev, &layer_count, &layer_props));
3804         ASSERT_EQ(layer_count, 0U);
3805     }
3806 }
3807 
3808 #if defined(_WIN32)
TEST(AppPackageDriverDiscovery, AppPackageTest)3809 TEST(AppPackageDriverDiscovery, AppPackageTest) {
3810     FrameworkEnvironment env;
3811     env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_2}.set_discovery_type(ManifestDiscoveryType::windows_app_package))
3812         .add_physical_device({});
3813 
3814     InstWrapper inst{env.vulkan_functions};
3815     inst.CheckCreate();
3816 }
3817 
3818 // Make sure that stale layer manifests (path to nonexistant file) which have the same name as real manifests don't cause the real
3819 // manifests to be skipped. Stale registry entries happen when a registry is written on layer/driver installation but not cleaned up
3820 // when the corresponding manifest is removed from the file system.
TEST(DuplicateRegistryEntries, Layers)3821 TEST(DuplicateRegistryEntries, Layers) {
3822     FrameworkEnvironment env{};
3823     env.add_icd(TestICDDetails(ManifestICD{}.set_lib_path(TEST_ICD_PATH_VERSION_2)));
3824 
3825     auto null_path = env.get_folder(ManifestLocation::null).location() / "test_layer.json";
3826 
3827     env.platform_shim->add_manifest(ManifestCategory::explicit_layer, null_path.str());
3828 
3829     const char* layer_name = "TestLayer";
3830     env.add_explicit_layer(
3831         ManifestLayer{}.add_layer(
3832             ManifestLayer::LayerDescription{}.set_name(layer_name).set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)),
3833         "test_layer.json");
3834 
3835     InstWrapper inst{env.vulkan_functions};
3836     inst.create_info.add_layer(layer_name);
3837     inst.CheckCreate();
3838 }
3839 
3840 // Check that the de-duplication of drivers found in both PnP and generic Khronos/Vulkan/Drivers doesn't result in the same thing
3841 // being added twice
TEST(DuplicateRegistryEntries, Drivers)3842 TEST(DuplicateRegistryEntries, Drivers) {
3843     FrameworkEnvironment env{};
3844     auto null_path = env.get_folder(ManifestLocation::null).location() / "test_icd_0.json";
3845     env.platform_shim->add_manifest(ManifestCategory::icd, null_path.str());
3846 
3847     env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA}.set_discovery_type(ManifestDiscoveryType::null_dir))
3848         .add_physical_device("physical_device_0")
3849         .set_adapterLUID(_LUID{10, 1000});
3850     env.platform_shim->add_d3dkmt_adapter(D3DKMT_Adapter{0, _LUID{10, 1000}}.add_driver_manifest_path(env.get_icd_manifest_path()));
3851 
3852     InstWrapper inst{env.vulkan_functions};
3853     FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
3854     inst.CheckCreate();
3855     ASSERT_TRUE(env.debug_log.find(std::string("Skipping adding of json file \"") + null_path.str() +
3856                                    "\" from registry \"HKEY_LOCAL_MACHINE\\" VK_DRIVERS_INFO_REGISTRY_LOC
3857                                    "\" to the list due to duplication"));
3858 }
3859 #endif
3860 
TEST(LibraryLoading, SystemLocations)3861 TEST(LibraryLoading, SystemLocations) {
3862     FrameworkEnvironment env{};
3863     EnvVarWrapper ld_library_path("LD_LIBRARY_PATH", env.get_folder(ManifestLocation::driver).location().str());
3864     ld_library_path.add_to_list(env.get_folder(ManifestLocation::explicit_layer).location().str());
3865 
3866     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2).set_library_path_type(LibraryPathType::default_search_paths))
3867                        .add_physical_device({});
3868     const char* fake_ext_name = "VK_FAKE_extension";
3869     driver.physical_devices.back().add_extension(fake_ext_name);
3870 
3871     const char* layer_name = "TestLayer";
3872     env.add_explicit_layer(
3873         TestLayerDetails{ManifestLayer{}.add_layer(
3874                              ManifestLayer::LayerDescription{}.set_name(layer_name).set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)),
3875                          "test_layer.json"}
3876             .set_library_path_type(LibraryPathType::default_search_paths));
3877 
3878     auto props = env.GetLayerProperties(1);
3879     ASSERT_TRUE(string_eq(props.at(0).layerName, layer_name));
3880 
3881     InstWrapper inst{env.vulkan_functions};
3882     inst.create_info.add_layer(layer_name);
3883     FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
3884     inst.CheckCreate();
3885 
3886     auto phys_dev = inst.GetPhysDev();
3887 
3888     auto active_props = inst.GetActiveLayers(phys_dev, 1);
3889     ASSERT_TRUE(string_eq(active_props.at(0).layerName, layer_name));
3890 
3891     auto device_extensions = inst.EnumerateDeviceExtensions(phys_dev, 1);
3892     ASSERT_TRUE(string_eq(device_extensions.at(0).extensionName, fake_ext_name));
3893 }
3894 
3895 #if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__)
3896 // Check that valid symlinks do not cause the loader to crash when directly in an XDG env-var
TEST(ManifestDiscovery, ValidSymlinkInXDGEnvVar)3897 TEST(ManifestDiscovery, ValidSymlinkInXDGEnvVar) {
3898     FrameworkEnvironment env{FrameworkSettings{}.set_enable_default_search_paths(false)};
3899     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_discovery_type(ManifestDiscoveryType::override_folder))
3900         .add_physical_device({});
3901     auto driver_path = env.get_icd_manifest_path(0);
3902     std::string symlink_name = "symlink_to_driver.json";
3903     fs::path symlink_path = env.get_folder(ManifestLocation::driver_env_var).location() / symlink_name;
3904     env.get_folder(ManifestLocation::driver_env_var).add_existing_file(symlink_name);
3905     int res = symlink(driver_path.c_str(), symlink_path.c_str());
3906     ASSERT_EQ(res, 0);
3907     EnvVarWrapper xdg_config_dirs_env_var{"XDG_CONFIG_DIRS", symlink_path.str()};
3908 
3909     InstWrapper inst{env.vulkan_functions};
3910     FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
3911     inst.CheckCreate();
3912 }
3913 
3914 // Check that valid symlinks do not cause the loader to crash
TEST(ManifestDiscovery, ValidSymlink)3915 TEST(ManifestDiscovery, ValidSymlink) {
3916     FrameworkEnvironment env{FrameworkSettings{}.set_enable_default_search_paths(false)};
3917     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_discovery_type(ManifestDiscoveryType::override_folder))
3918         .add_physical_device({});
3919 
3920     auto driver_path = env.get_icd_manifest_path(0);
3921     std::string symlink_name = "symlink_to_driver.json";
3922     fs::path symlink_path = env.get_folder(ManifestLocation::driver_env_var).location() / symlink_name;
3923     env.get_folder(ManifestLocation::driver_env_var).add_existing_file(symlink_name);
3924     int res = symlink(driver_path.c_str(), symlink_path.c_str());
3925     ASSERT_EQ(res, 0);
3926 
3927     env.platform_shim->set_fake_path(ManifestCategory::icd, env.get_folder(ManifestLocation::driver_env_var).location());
3928 
3929     InstWrapper inst{env.vulkan_functions};
3930     FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
3931     inst.CheckCreate();
3932 }
3933 
3934 // Check that invalid symlinks do not cause the loader to crash when directly in an XDG env-var
TEST(ManifestDiscovery, InvalidSymlinkXDGEnvVar)3935 TEST(ManifestDiscovery, InvalidSymlinkXDGEnvVar) {
3936     FrameworkEnvironment env{FrameworkSettings{}.set_enable_default_search_paths(false)};
3937     std::string symlink_name = "symlink_to_nothing.json";
3938     fs::path symlink_path = env.get_folder(ManifestLocation::driver_env_var).location() / symlink_name;
3939     fs::path invalid_driver_path = env.get_folder(ManifestLocation::driver).location() / "nothing_here.json";
3940     int res = symlink(invalid_driver_path.c_str(), symlink_path.c_str());
3941     ASSERT_EQ(res, 0);
3942     env.get_folder(ManifestLocation::driver_env_var).add_existing_file(symlink_name);
3943 
3944     EnvVarWrapper xdg_config_dirs_env_var{symlink_path.str()};
3945 
3946     InstWrapper inst{env.vulkan_functions};
3947     FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
3948     inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER);
3949 }
3950 
3951 // Check that invalid symlinks do not cause the loader to crash
TEST(ManifestDiscovery, InvalidSymlink)3952 TEST(ManifestDiscovery, InvalidSymlink) {
3953     FrameworkEnvironment env{FrameworkSettings{}.set_enable_default_search_paths(false)};
3954     std::string symlink_name = "symlink_to_nothing.json";
3955     fs::path symlink_path = env.get_folder(ManifestLocation::driver).location() / symlink_name;
3956     fs::path invalid_driver_path = env.get_folder(ManifestLocation::driver_env_var).location() / "nothing_here.json";
3957     int res = symlink(invalid_driver_path.c_str(), symlink_path.c_str());
3958     ASSERT_EQ(res, 0);
3959     env.get_folder(ManifestLocation::driver).add_existing_file(symlink_name);
3960 
3961     env.platform_shim->set_fake_path(ManifestCategory::icd, env.get_folder(ManifestLocation::driver_env_var).location());
3962 
3963     InstWrapper inst{env.vulkan_functions};
3964     FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
3965     inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER);
3966 }
3967 #endif
3968 
3969 #if defined(__APPLE__)
3970 // Add two drivers, one to the bundle and one to the system locations
TEST(ManifestDiscovery, AppleBundles)3971 TEST(ManifestDiscovery, AppleBundles) {
3972     FrameworkEnvironment env{};
3973     env.setup_macos_bundle();
3974     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_discovery_type(ManifestDiscoveryType::macos_bundle));
3975     env.get_test_icd(0).physical_devices.push_back({});
3976     env.get_test_icd(0).physical_devices.at(0).properties.deviceID = 1337;
3977     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
3978     env.get_test_icd(1).physical_devices.push_back({});
3979     env.get_test_icd(1).physical_devices.at(0).properties.deviceID = 9999;
3980 
3981     InstWrapper inst{env.vulkan_functions};
3982     ASSERT_NO_FATAL_FAILURE(inst.CheckCreate());
3983     auto physical_devices = inst.GetPhysDevs();
3984     ASSERT_EQ(1, physical_devices.size());
3985 
3986     // Verify that this is the 'right' GPU, aka the one from the bundle
3987     VkPhysicalDeviceProperties props{};
3988     inst->vkGetPhysicalDeviceProperties(physical_devices[0], &props);
3989     ASSERT_EQ(env.get_test_icd(0).physical_devices.at(0).properties.deviceID, props.deviceID);
3990 }
3991 
3992 // Add two drivers, one to the bundle and one using the driver env-var
TEST(ManifestDiscovery, AppleBundlesEnvVarActive)3993 TEST(ManifestDiscovery, AppleBundlesEnvVarActive) {
3994     FrameworkEnvironment env{};
3995     env.setup_macos_bundle();
3996     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_discovery_type(ManifestDiscoveryType::macos_bundle));
3997     env.get_test_icd(0).physical_devices.push_back({});
3998     env.get_test_icd(0).physical_devices.at(0).properties.deviceID = 1337;
3999     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_discovery_type(ManifestDiscoveryType::env_var));
4000     env.get_test_icd(1).physical_devices.push_back({});
4001     env.get_test_icd(1).physical_devices.at(0).properties.deviceID = 9999;
4002 
4003     InstWrapper inst{env.vulkan_functions};
4004     ASSERT_NO_FATAL_FAILURE(inst.CheckCreate());
4005     auto physical_devices = inst.GetPhysDevs();
4006     ASSERT_EQ(1, physical_devices.size());
4007 
4008     // Verify that this is the 'right' GPU, aka the one from the env-var
4009     VkPhysicalDeviceProperties props{};
4010     inst->vkGetPhysicalDeviceProperties(physical_devices[0], &props);
4011     ASSERT_EQ(env.get_test_icd(1).physical_devices.at(0).properties.deviceID, props.deviceID);
4012 }
4013 #endif
4014 
TEST(LayerCreatesDevice, Basic)4015 TEST(LayerCreatesDevice, Basic) {
4016     FrameworkEnvironment env{};
4017     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device({});
4018 
4019     env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
4020                                                          .set_name("implicit_layer_name")
4021                                                          .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
4022                                                          .set_disable_environment("DISABLE_ME")),
4023                            "implicit_test_layer.json");
4024     env.get_test_layer().set_call_create_device_while_create_device_is_called(true);
4025     env.get_test_layer().set_physical_device_index_to_use_during_create_device(0);
4026 
4027     env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
4028                                                          .set_name("implicit_layer_name2")
4029                                                          .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
4030                                                          .set_disable_environment("DISABLE_ME")),
4031                            "implicit_test_layer2.json");
4032 
4033     InstWrapper inst{env.vulkan_functions};
4034     inst.CheckCreate();
4035 
4036     DeviceWrapper dev{inst};
4037     dev.CheckCreate(inst.GetPhysDev());
4038 }
4039 
TEST(LayerCreatesDevice, DifferentPhysicalDevice)4040 TEST(LayerCreatesDevice, DifferentPhysicalDevice) {
4041     FrameworkEnvironment env{};
4042     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
4043     env.get_test_icd(0).physical_devices.emplace_back("Device0");
4044     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
4045     env.get_test_icd(1).physical_devices.emplace_back("Device1");
4046 
4047     env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
4048                                                          .set_name("implicit_layer_name")
4049                                                          .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
4050                                                          .set_disable_environment("DISABLE_ME")),
4051                            "implicit_test_layer.json");
4052     env.get_test_layer().set_call_create_device_while_create_device_is_called(true);
4053     env.get_test_layer().set_physical_device_index_to_use_during_create_device(1);
4054 
4055     env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
4056                                                          .set_name("implicit_layer_name2")
4057                                                          .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
4058                                                          .set_disable_environment("DISABLE_ME")),
4059                            "implicit_test_layer2.json");
4060 
4061     InstWrapper inst{env.vulkan_functions};
4062     inst.CheckCreate();
4063 
4064     auto phys_devs = inst.GetPhysDevs();
4065 
4066     DeviceWrapper dev{inst};
4067     dev.CheckCreate(phys_devs.at(0));
4068 }
4069 
TEST(Layer, pfnNextGetInstanceProcAddr_should_not_return_layers_own_functions)4070 TEST(Layer, pfnNextGetInstanceProcAddr_should_not_return_layers_own_functions) {
4071     FrameworkEnvironment env{};
4072     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device({});
4073 
4074     env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
4075                                                          .set_name("implicit_layer_name")
4076                                                          .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
4077                                                          .set_disable_environment("DISABLE_ME")),
4078                            "implicit_test_layer.json");
4079     env.get_test_layer(0).set_check_if_EnumDevExtProps_is_same_as_queried_function(true);
4080 
4081     InstWrapper inst{env.vulkan_functions};
4082     inst.CheckCreate();
4083 
4084     auto phys_devs = inst.GetPhysDevs();
4085 
4086     DeviceWrapper dev{inst};
4087     dev.CheckCreate(phys_devs.at(0));
4088 }
4089 
TEST(Layer, LLP_LAYER_21)4090 TEST(Layer, LLP_LAYER_21) {
4091     FrameworkEnvironment env{};
4092     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device({});
4093 
4094     env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
4095                                                          .set_name("implicit_layer_name")
4096                                                          .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
4097                                                          .set_disable_environment("DISABLE_ME")),
4098                            "implicit_test_layer.json");
4099     env.get_test_layer(0).set_clobber_pInstance(true);
4100 
4101     InstWrapper inst{env.vulkan_functions};
4102     FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
4103 #if defined(WIN32)
4104 #if defined(_WIN64)
4105     ASSERT_DEATH(
4106         inst.CheckCreate(),
4107         testing::ContainsRegex(
4108             R"(terminator_CreateInstance: Instance pointer \(................\) has invalid MAGIC value 0x00000000. Instance value )"
4109             R"(possibly corrupted by active layer \(Policy #LLP_LAYER_21\))"));
4110 #else
4111     ASSERT_DEATH(
4112         inst.CheckCreate(),
4113         testing::ContainsRegex(
4114             R"(terminator_CreateInstance: Instance pointer \(........\) has invalid MAGIC value 0x00000000. Instance value )"
4115             R"(possibly corrupted by active layer \(Policy #LLP_LAYER_21\))"));
4116 #endif
4117 #else
4118     ASSERT_DEATH(
4119         inst.CheckCreate(),
4120         testing::ContainsRegex(
4121             R"(terminator_CreateInstance: Instance pointer \(0x[0-9A-Fa-f]+\) has invalid MAGIC value 0x00000000. Instance value )"
4122             R"(possibly corrupted by active layer \(Policy #LLP_LAYER_21\))"));
4123 #endif
4124 }
4125 
TEST(Layer, LLP_LAYER_22)4126 TEST(Layer, LLP_LAYER_22) {
4127     FrameworkEnvironment env{};
4128     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device({});
4129 
4130     env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
4131                                                          .set_name("implicit_layer_name")
4132                                                          .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
4133                                                          .set_disable_environment("DISABLE_ME")),
4134                            "implicit_test_layer.json");
4135     env.get_test_layer(0).set_clobber_pDevice(true);
4136 
4137     InstWrapper inst{env.vulkan_functions};
4138     inst.create_info.add_extension("VK_EXT_debug_utils");
4139     inst.CheckCreate();
4140 
4141     DebugUtilsWrapper log{inst};
4142     CreateDebugUtilsMessenger(log);
4143 
4144     DeviceWrapper dev{inst};
4145 #if defined(WIN32)
4146 #if defined(_WIN64)
4147     ASSERT_DEATH(
4148         dev.CheckCreate(inst.GetPhysDev()),
4149         testing::ContainsRegex(
4150             R"(terminator_CreateDevice: Device pointer \(................\) has invalid MAGIC value 0x00000000. The expected value is 0x10ADED040410ADED. Device value )"
4151             R"(possibly corrupted by active layer \(Policy #LLP_LAYER_22\))"));
4152 #else
4153     ASSERT_DEATH(
4154         dev.CheckCreate(inst.GetPhysDev()),
4155         testing::ContainsRegex(
4156             R"(terminator_CreateDevice: Device pointer \(........\) has invalid MAGIC value 0x00000000. The expected value is 0x10ADED040410ADED. Device value )"
4157             R"(possibly corrupted by active layer \(Policy #LLP_LAYER_22\))"));
4158 #endif
4159 #else
4160     ASSERT_DEATH(
4161         dev.CheckCreate(inst.GetPhysDev()),
4162         testing::ContainsRegex(
4163             R"(terminator_CreateDevice: Device pointer \(0x[0-9A-Fa-f]+\) has invalid MAGIC value 0x00000000. The expected value is 0x10ADED040410ADED. Device value )"
4164             R"(possibly corrupted by active layer \(Policy #LLP_LAYER_22\))"));
4165 #endif
4166 }
4167 
TEST(InvalidManifest, ICD)4168 TEST(InvalidManifest, ICD) {
4169     FrameworkEnvironment env{};
4170     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device({});
4171 
4172     std::vector<std::string> invalid_jsons;
4173     invalid_jsons.push_back(",");
4174     invalid_jsons.push_back("{},[]");
4175     invalid_jsons.push_back("{ \"foo\":\"bar\", }");
4176     invalid_jsons.push_back("{\"foo\":\"bar\", \"baz\": [], },");
4177     invalid_jsons.push_back("{\"foo\":\"bar\", \"baz\": [{},] },");
4178     invalid_jsons.push_back("{\"foo\":\"bar\", \"baz\": {\"fee\"} },");
4179     invalid_jsons.push_back("{\"\":\"bar\", \"baz\": {}");
4180     invalid_jsons.push_back("{\"foo\":\"bar\", \"baz\": {\"fee\":1234, true, \"ab\":\"bc\"} },");
4181 
4182     for (size_t i = 0; i < invalid_jsons.size(); i++) {
4183         auto file_name = std::string("invalid_driver_") + std::to_string(i) + ".json";
4184         fs::path new_path = env.get_folder(ManifestLocation::driver).write_manifest(file_name, invalid_jsons[i]);
4185         env.platform_shim->add_manifest(ManifestCategory::icd, new_path);
4186     }
4187 
4188     InstWrapper inst{env.vulkan_functions};
4189     inst.CheckCreate();
4190 }
4191 
TEST(InvalidManifest, Layer)4192 TEST(InvalidManifest, Layer) {
4193     FrameworkEnvironment env{};
4194     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device({});
4195 
4196     std::vector<std::string> invalid_jsons;
4197     invalid_jsons.push_back(",");
4198     invalid_jsons.push_back("{},[]");
4199     invalid_jsons.push_back("{ \"foo\":\"bar\", }");
4200     invalid_jsons.push_back("{\"foo\":\"bar\", \"baz\": [], },");
4201     invalid_jsons.push_back("{\"foo\":\"bar\", \"baz\": [{},] },");
4202     invalid_jsons.push_back("{\"foo\":\"bar\", \"baz\": {\"fee\"} },");
4203     invalid_jsons.push_back("{\"\":\"bar\", \"baz\": {}");
4204     invalid_jsons.push_back("{\"foo\":\"bar\", \"baz\": {\"fee\":1234, true, \"ab\":\"bc\"} },");
4205 
4206     for (size_t i = 0; i < invalid_jsons.size(); i++) {
4207         auto file_name = std::string("invalid_implicit_layer_") + std::to_string(i) + ".json";
4208         fs::path new_path = env.get_folder(ManifestLocation::implicit_layer).write_manifest(file_name, invalid_jsons[i]);
4209         env.platform_shim->add_manifest(ManifestCategory::implicit_layer, new_path);
4210     }
4211 
4212     InstWrapper inst{env.vulkan_functions};
4213     inst.CheckCreate();
4214 }
4215 #if defined(WIN32)
add_dxgi_adapter(FrameworkEnvironment& env, const char* name, LUID luid, uint32_t vendor_id)4216 void add_dxgi_adapter(FrameworkEnvironment& env, const char* name, LUID luid, uint32_t vendor_id) {
4217     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6).set_discovery_type(ManifestDiscoveryType::null_dir));
4218     driver.set_min_icd_interface_version(5);
4219     driver.set_max_icd_interface_version(6);
4220     driver.setup_WSI();
4221     driver.set_icd_api_version(VK_API_VERSION_1_1);
4222     driver.physical_devices.emplace_back(name);
4223     auto& pd0 = driver.physical_devices.back();
4224     pd0.properties.apiVersion = VK_API_VERSION_1_1;
4225 
4226     DXGI_ADAPTER_DESC1 desc{};
4227     desc.VendorId = known_driver_list.at(vendor_id).vendor_id;
4228     desc.AdapterLuid = luid;
4229     auto wide_name = conver_str_to_wstr(name);
4230     wcsncpy_s(desc.Description, 128, wide_name.c_str(), wide_name.size());
4231     driver.set_adapterLUID(desc.AdapterLuid);
4232     env.platform_shim->add_dxgi_adapter(GpuType::discrete, desc);
4233 
4234     env.platform_shim->add_d3dkmt_adapter(
4235         D3DKMT_Adapter{static_cast<UINT>(env.icds.size()) - 1U, desc.AdapterLuid}.add_driver_manifest_path(
4236             env.get_icd_manifest_path(env.icds.size() - 1)));
4237 }
4238 
TEST(EnumerateAdapterPhysicalDevices, SameAdapterLUID_reordered)4239 TEST(EnumerateAdapterPhysicalDevices, SameAdapterLUID_reordered) {
4240     FrameworkEnvironment env;
4241 
4242     uint32_t physical_count = 3;
4243 
4244     // Physical devices are enumerate in reverse order to the drivers insertion into the test framework
4245     add_dxgi_adapter(env, "physical_device_2", LUID{10, 100}, 2);
4246     add_dxgi_adapter(env, "physical_device_1", LUID{20, 200}, 1);
4247     add_dxgi_adapter(env, "physical_device_0", LUID{10, 100}, 2);
4248 
4249     {
4250         uint32_t returned_physical_count = 0;
4251         InstWrapper inst{env.vulkan_functions};
4252         inst.create_info.setup_WSI().set_api_version(VK_API_VERSION_1_1);
4253         inst.CheckCreate();
4254 
4255         ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, nullptr));
4256         ASSERT_EQ(physical_count, returned_physical_count);
4257         std::vector<VkPhysicalDevice> physical_device_handles{returned_physical_count};
4258         ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count,
4259                                                                               physical_device_handles.data()));
4260         ASSERT_EQ(physical_count, returned_physical_count);
4261 
4262         VkPhysicalDeviceProperties phys_dev_props[3]{};
4263         env.vulkan_functions.vkGetPhysicalDeviceProperties(physical_device_handles[0], &(phys_dev_props[0]));
4264         env.vulkan_functions.vkGetPhysicalDeviceProperties(physical_device_handles[1], &(phys_dev_props[1]));
4265         env.vulkan_functions.vkGetPhysicalDeviceProperties(physical_device_handles[2], &(phys_dev_props[2]));
4266 
4267         EXPECT_TRUE(string_eq(phys_dev_props[0].deviceName, "physical_device_0"));
4268         EXPECT_TRUE(string_eq(phys_dev_props[1].deviceName, "physical_device_2"));
4269         // Because LUID{10,100} is encountered first, all physical devices which correspond to that LUID are enumerated before any
4270         // other physical devices.
4271         EXPECT_TRUE(string_eq(phys_dev_props[2].deviceName, "physical_device_1"));
4272 
4273         // Check that both devices do not report VK_LAYERED_DRIVER_UNDERLYING_API_D3D12_MSFT
4274         VkPhysicalDeviceLayeredDriverPropertiesMSFT layered_driver_properties_msft{};
4275         layered_driver_properties_msft.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LAYERED_DRIVER_PROPERTIES_MSFT;
4276         VkPhysicalDeviceProperties2 props2{};
4277         props2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
4278         props2.pNext = (void*)&layered_driver_properties_msft;
4279 
4280         env.vulkan_functions.vkGetPhysicalDeviceProperties2(physical_device_handles[0], &props2);
4281         EXPECT_EQ(layered_driver_properties_msft.underlyingAPI, VK_LAYERED_DRIVER_UNDERLYING_API_NONE_MSFT);
4282 
4283         env.vulkan_functions.vkGetPhysicalDeviceProperties2(physical_device_handles[1], &props2);
4284         EXPECT_EQ(layered_driver_properties_msft.underlyingAPI, VK_LAYERED_DRIVER_UNDERLYING_API_NONE_MSFT);
4285 
4286         env.vulkan_functions.vkGetPhysicalDeviceProperties2(physical_device_handles[2], &props2);
4287         EXPECT_EQ(layered_driver_properties_msft.underlyingAPI, VK_LAYERED_DRIVER_UNDERLYING_API_NONE_MSFT);
4288     }
4289     // Set the first physical device that is enumerated to be a 'layered' driver so it should be swapped with the first physical
4290     // device
4291     env.get_test_icd(2).physical_devices.back().layered_driver_underlying_api = VK_LAYERED_DRIVER_UNDERLYING_API_D3D12_MSFT;
4292     {
4293         uint32_t returned_physical_count = 0;
4294         InstWrapper inst{env.vulkan_functions};
4295         inst.create_info.setup_WSI().set_api_version(VK_API_VERSION_1_1);
4296         inst.CheckCreate();
4297 
4298         ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, nullptr));
4299         ASSERT_EQ(physical_count, returned_physical_count);
4300         std::vector<VkPhysicalDevice> physical_device_handles{returned_physical_count};
4301         ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count,
4302                                                                               physical_device_handles.data()));
4303         ASSERT_EQ(physical_count, returned_physical_count);
4304 
4305         VkPhysicalDeviceProperties phys_dev_props[3]{};
4306         env.vulkan_functions.vkGetPhysicalDeviceProperties(physical_device_handles[0], &(phys_dev_props[0]));
4307         env.vulkan_functions.vkGetPhysicalDeviceProperties(physical_device_handles[1], &(phys_dev_props[1]));
4308         env.vulkan_functions.vkGetPhysicalDeviceProperties(physical_device_handles[2], &(phys_dev_props[2]));
4309 
4310         // Because the 'last' driver has the layered_driver set to D3D12, the order is modified
4311         EXPECT_TRUE(string_eq(phys_dev_props[0].deviceName, "physical_device_2"));
4312         EXPECT_TRUE(string_eq(phys_dev_props[1].deviceName, "physical_device_0"));
4313         // Because LUID{10,100} is encountered first, all physical devices which correspond to that LUID are enumerated before any
4314         // other physical devices.
4315         EXPECT_TRUE(string_eq(phys_dev_props[2].deviceName, "physical_device_1"));
4316 
4317         // Check that the correct physical device reports VK_LAYERED_DRIVER_UNDERLYING_API_D3D12_MSFT
4318         VkPhysicalDeviceLayeredDriverPropertiesMSFT layered_driver_properties_msft{};
4319         layered_driver_properties_msft.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LAYERED_DRIVER_PROPERTIES_MSFT;
4320         VkPhysicalDeviceProperties2 props2{};
4321         props2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
4322         props2.pNext = (void*)&layered_driver_properties_msft;
4323 
4324         env.vulkan_functions.vkGetPhysicalDeviceProperties2(physical_device_handles[0], &props2);
4325         EXPECT_EQ(layered_driver_properties_msft.underlyingAPI, VK_LAYERED_DRIVER_UNDERLYING_API_NONE_MSFT);
4326 
4327         env.vulkan_functions.vkGetPhysicalDeviceProperties2(physical_device_handles[1], &props2);
4328         EXPECT_EQ(layered_driver_properties_msft.underlyingAPI, VK_LAYERED_DRIVER_UNDERLYING_API_D3D12_MSFT);
4329 
4330         env.vulkan_functions.vkGetPhysicalDeviceProperties2(physical_device_handles[2], &props2);
4331         EXPECT_EQ(layered_driver_properties_msft.underlyingAPI, VK_LAYERED_DRIVER_UNDERLYING_API_NONE_MSFT);
4332     }
4333 }
4334 
TEST(EnumerateAdapterPhysicalDevices, SameAdapterLUID_same_order)4335 TEST(EnumerateAdapterPhysicalDevices, SameAdapterLUID_same_order) {
4336     FrameworkEnvironment env;
4337 
4338     uint32_t physical_count = 3;
4339 
4340     // Physical devices are enumerate in reverse order to the drivers insertion into the test framework
4341     add_dxgi_adapter(env, "physical_device_2", LUID{10, 100}, 2);
4342     add_dxgi_adapter(env, "physical_device_1", LUID{20, 200}, 1);
4343     add_dxgi_adapter(env, "physical_device_0", LUID{10, 100}, 2);
4344 
4345     // Set the last physical device that is enumerated last to be a 'layered'  physical device - no swapping should occur
4346     env.get_test_icd(0).physical_devices.back().layered_driver_underlying_api = VK_LAYERED_DRIVER_UNDERLYING_API_D3D12_MSFT;
4347 
4348     uint32_t returned_physical_count = 0;
4349     InstWrapper inst{env.vulkan_functions};
4350     inst.create_info.setup_WSI().set_api_version(VK_API_VERSION_1_1);
4351     inst.CheckCreate();
4352 
4353     ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, nullptr));
4354     ASSERT_EQ(physical_count, returned_physical_count);
4355     std::vector<VkPhysicalDevice> physical_device_handles{returned_physical_count};
4356     ASSERT_EQ(VK_SUCCESS,
4357               env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, physical_device_handles.data()));
4358     ASSERT_EQ(physical_count, returned_physical_count);
4359 
4360     VkPhysicalDeviceProperties phys_dev_props[3]{};
4361     env.vulkan_functions.vkGetPhysicalDeviceProperties(physical_device_handles[0], &(phys_dev_props[0]));
4362     env.vulkan_functions.vkGetPhysicalDeviceProperties(physical_device_handles[1], &(phys_dev_props[1]));
4363     env.vulkan_functions.vkGetPhysicalDeviceProperties(physical_device_handles[2], &(phys_dev_props[2]));
4364 
4365     // Make sure that reordering doesn't occur if the MSFT layered driver appears second
4366     EXPECT_TRUE(string_eq(phys_dev_props[0].deviceName, "physical_device_0"));
4367     EXPECT_TRUE(string_eq(phys_dev_props[1].deviceName, "physical_device_2"));
4368     // Because LUID{10,100} is encountered first, all physical devices which correspond to that LUID are enumerated before any
4369     // other physical devices.
4370     EXPECT_TRUE(string_eq(phys_dev_props[2].deviceName, "physical_device_1"));
4371 
4372     // Check that the correct physical device reports VK_LAYERED_DRIVER_UNDERLYING_API_D3D12_MSFT
4373     VkPhysicalDeviceLayeredDriverPropertiesMSFT layered_driver_properties_msft{};
4374     layered_driver_properties_msft.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LAYERED_DRIVER_PROPERTIES_MSFT;
4375     VkPhysicalDeviceProperties2 props2{};
4376     props2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
4377     props2.pNext = (void*)&layered_driver_properties_msft;
4378 
4379     env.vulkan_functions.vkGetPhysicalDeviceProperties2(physical_device_handles[0], &props2);
4380     EXPECT_EQ(layered_driver_properties_msft.underlyingAPI, VK_LAYERED_DRIVER_UNDERLYING_API_NONE_MSFT);
4381 
4382     env.vulkan_functions.vkGetPhysicalDeviceProperties2(physical_device_handles[1], &props2);
4383     EXPECT_EQ(layered_driver_properties_msft.underlyingAPI, VK_LAYERED_DRIVER_UNDERLYING_API_D3D12_MSFT);
4384 
4385     env.vulkan_functions.vkGetPhysicalDeviceProperties2(physical_device_handles[2], &props2);
4386     EXPECT_EQ(layered_driver_properties_msft.underlyingAPI, VK_LAYERED_DRIVER_UNDERLYING_API_NONE_MSFT);
4387 }
4388 #endif  // defined(WIN32)
4389