• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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();
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();
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(EnumeratePhysicalDevices,OneDriverWithWrongErrorCodes)1166 TEST(EnumeratePhysicalDevices, OneDriverWithWrongErrorCodes) {
1167     FrameworkEnvironment env;
1168     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
1169 
1170     InstWrapper inst{env.vulkan_functions};
1171     inst.create_info.set_api_version(VK_API_VERSION_1_1);
1172     inst.CheckCreate();
1173 
1174     {
1175         env.get_test_icd().set_enum_physical_devices_return_code(VK_ERROR_INITIALIZATION_FAILED);
1176         uint32_t returned_physical_count = 0;
1177         EXPECT_EQ(VK_ERROR_INITIALIZATION_FAILED,
1178                   env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, nullptr));
1179         EXPECT_EQ(returned_physical_count, 0);
1180     }
1181     {
1182         env.get_test_icd().set_enum_physical_devices_return_code(VK_ERROR_INCOMPATIBLE_DRIVER);
1183         uint32_t returned_physical_count = 0;
1184         EXPECT_EQ(VK_ERROR_INITIALIZATION_FAILED,
1185                   env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, nullptr));
1186         EXPECT_EQ(returned_physical_count, 0);
1187     }
1188     {
1189         env.get_test_icd().set_enum_physical_devices_return_code(VK_ERROR_SURFACE_LOST_KHR);
1190         uint32_t returned_physical_count = 0;
1191         EXPECT_EQ(VK_ERROR_INITIALIZATION_FAILED,
1192                   env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, nullptr));
1193         EXPECT_EQ(returned_physical_count, 0);
1194     }
1195 }
1196 
TEST(EnumeratePhysicalDevices,TwoDriversOneWithWrongErrorCodes)1197 TEST(EnumeratePhysicalDevices, TwoDriversOneWithWrongErrorCodes) {
1198     FrameworkEnvironment env;
1199     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device({});
1200     TestICD& icd1 = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
1201 
1202     InstWrapper inst{env.vulkan_functions};
1203     inst.create_info.set_api_version(VK_API_VERSION_1_1);
1204     inst.CheckCreate();
1205 
1206     {
1207         icd1.set_enum_physical_devices_return_code(VK_ERROR_INITIALIZATION_FAILED);
1208         uint32_t returned_physical_count = 0;
1209         EXPECT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, nullptr));
1210         EXPECT_EQ(returned_physical_count, 1);
1211     }
1212     {
1213         icd1.set_enum_physical_devices_return_code(VK_ERROR_INCOMPATIBLE_DRIVER);
1214         uint32_t returned_physical_count = 0;
1215         EXPECT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, nullptr));
1216         EXPECT_EQ(returned_physical_count, 1);
1217     }
1218     {
1219         icd1.set_enum_physical_devices_return_code(VK_ERROR_SURFACE_LOST_KHR);
1220         uint32_t returned_physical_count = 0;
1221         EXPECT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, nullptr));
1222         EXPECT_EQ(returned_physical_count, 1);
1223     }
1224 }
1225 
TEST(CreateDevice,ExtensionNotPresent)1226 TEST(CreateDevice, ExtensionNotPresent) {
1227     FrameworkEnvironment env{};
1228     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device("physical_device_0");
1229 
1230     InstWrapper inst{env.vulkan_functions};
1231     inst.CheckCreate();
1232 
1233     VkPhysicalDevice phys_dev = inst.GetPhysDev();
1234 
1235     DeviceWrapper dev{inst};
1236     dev.create_info.add_extension("NotPresent");
1237 
1238     dev.CheckCreate(phys_dev, VK_ERROR_EXTENSION_NOT_PRESENT);
1239 }
1240 
1241 // LX535 / MI-76: Device layers are deprecated.
1242 // Ensure that no errors occur if a bogus device layer list is passed to vkCreateDevice.
1243 // https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#extendingvulkan-layers-devicelayerdeprecation
TEST(CreateDevice,LayersNotPresent)1244 TEST(CreateDevice, LayersNotPresent) {
1245     FrameworkEnvironment env{};
1246     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device("physical_device_0");
1247 
1248     InstWrapper inst{env.vulkan_functions};
1249     inst.CheckCreate();
1250 
1251     VkPhysicalDevice phys_dev = inst.GetPhysDev();
1252 
1253     DeviceWrapper dev{inst};
1254     dev.create_info.add_layer("NotPresent");
1255 
1256     dev.CheckCreate(phys_dev);
1257 }
1258 
1259 // Device layers are deprecated.
1260 // Ensure that no error occur if instance and device are created with the same list of layers.
1261 // https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#extendingvulkan-layers-devicelayerdeprecation
TEST(CreateDevice,MatchInstanceAndDeviceLayers)1262 TEST(CreateDevice, MatchInstanceAndDeviceLayers) {
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     inst.create_info.add_layer(layer_name);
1274     inst.CheckCreate();
1275 
1276     VkPhysicalDevice phys_dev = inst.GetPhysDev();
1277 
1278     DeviceWrapper dev{inst};
1279     dev.create_info.add_layer(layer_name);
1280 
1281     dev.CheckCreate(phys_dev);
1282 }
1283 
1284 // Device layers are deprecated.
1285 // Ensure that a message is generated when instance and device are created with different list of layers.
1286 // At best , the user can list only instance layers in the device layer list
1287 // https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#extendingvulkan-layers-devicelayerdeprecation
TEST(CreateDevice,UnmatchInstanceAndDeviceLayers)1288 TEST(CreateDevice, UnmatchInstanceAndDeviceLayers) {
1289     FrameworkEnvironment env{};
1290     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device("physical_device_0");
1291 
1292     const char* layer_name = "TestLayer";
1293     env.add_explicit_layer(
1294         ManifestLayer{}.add_layer(
1295             ManifestLayer::LayerDescription{}.set_name(layer_name).set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)),
1296         "test_layer.json");
1297 
1298     DebugUtilsLogger debug_log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT};
1299     InstWrapper inst{env.vulkan_functions};
1300     FillDebugUtilsCreateDetails(inst.create_info, debug_log);
1301     inst.CheckCreate();
1302 
1303     DebugUtilsWrapper log{inst, VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT};
1304     CreateDebugUtilsMessenger(log);
1305 
1306     VkPhysicalDevice phys_dev = inst.GetPhysDev();
1307 
1308     DeviceWrapper dev{inst};
1309     dev.create_info.add_layer(layer_name);
1310 
1311     dev.CheckCreate(phys_dev);
1312 
1313     ASSERT_TRUE(
1314         log.find("loader_create_device_chain: Using deprecated and ignored 'ppEnabledLayerNames' member of 'VkDeviceCreateInfo' "
1315                  "when creating a Vulkan device."));
1316 }
1317 
1318 // Device layers are deprecated.
1319 // Ensure that when VkInstanceCreateInfo is deleted, the check of the instance layer lists is running correctly during VkDevice
1320 // creation
1321 // https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#extendingvulkan-layers-devicelayerdeprecation
TEST(CreateDevice,CheckCopyOfInstanceLayerNames)1322 TEST(CreateDevice, CheckCopyOfInstanceLayerNames) {
1323     FrameworkEnvironment env{};
1324     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device("physical_device_0");
1325 
1326     const char* layer_name = "TestLayer";
1327     env.add_explicit_layer(
1328         ManifestLayer{}.add_layer(
1329             ManifestLayer::LayerDescription{}.set_name(layer_name).set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)),
1330         "test_layer.json");
1331 
1332     InstWrapper inst{env.vulkan_functions};
1333     {
1334         // We intentionally create a local InstanceCreateInfo that goes out of scope at the } so that when dev.CheckCreate is called
1335         // the layer name pointers are no longer valid
1336         InstanceCreateInfo create_info{};
1337         create_info.add_layer(layer_name);
1338         inst.CheckCreateWithInfo(create_info);
1339     }
1340 
1341     VkPhysicalDevice phys_dev = inst.GetPhysDev();
1342 
1343     DeviceWrapper dev{inst};
1344     dev.create_info.add_layer(layer_name);
1345 
1346     dev.CheckCreate(phys_dev);
1347 }
1348 
TEST(CreateDevice,ConsecutiveCreate)1349 TEST(CreateDevice, ConsecutiveCreate) {
1350     FrameworkEnvironment env{};
1351     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
1352 
1353     for (uint32_t i = 0; i < 100; i++) {
1354         driver.physical_devices.emplace_back("physical_device_0");
1355     }
1356     InstWrapper inst{env.vulkan_functions};
1357     inst.CheckCreate();
1358 
1359     auto phys_devs = inst.GetPhysDevs(100);
1360     for (uint32_t i = 0; i < 100; i++) {
1361         DeviceWrapper dev{inst};
1362         dev.CheckCreate(phys_devs[i]);
1363     }
1364 }
1365 
TEST(CreateDevice,ConsecutiveCreateWithoutDestruction)1366 TEST(CreateDevice, ConsecutiveCreateWithoutDestruction) {
1367     FrameworkEnvironment env{};
1368     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
1369 
1370     for (uint32_t i = 0; i < 100; i++) {
1371         driver.physical_devices.emplace_back("physical_device_0");
1372     }
1373     InstWrapper inst{env.vulkan_functions};
1374     inst.CheckCreate();
1375 
1376     auto phys_devs = inst.GetPhysDevs(100);
1377 
1378     std::vector<DeviceWrapper> devices;
1379     for (uint32_t i = 0; i < 100; i++) {
1380         devices.emplace_back(inst);
1381         DeviceWrapper& dev = devices.back();
1382 
1383         dev.CheckCreate(phys_devs[i]);
1384     }
1385 }
1386 
TEST(TryLoadWrongBinaries,WrongICD)1387 TEST(TryLoadWrongBinaries, WrongICD) {
1388     FrameworkEnvironment env{};
1389     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device("physical_device_0");
1390     env.add_icd(TestICDDetails(CURRENT_PLATFORM_DUMMY_BINARY_WRONG_TYPE).set_is_fake(true));
1391 
1392     DebugUtilsLogger log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
1393     InstWrapper inst{env.vulkan_functions};
1394     FillDebugUtilsCreateDetails(inst.create_info, log);
1395     inst.CheckCreate();
1396 
1397 #if _WIN32 || _WIN64
1398     ASSERT_TRUE(log.find("Failed to open dynamic library"));
1399 #endif
1400 #if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__GNU__) || defined(__QNX__)
1401 #if defined(__x86_64__) || __ppc64__ || __aarch64__
1402     ASSERT_TRUE(log.find("wrong ELF class: ELFCLASS32"));
1403 #else
1404     ASSERT_TRUE(log.find("wrong ELF class: ELFCLASS64"));
1405 #endif
1406 #endif
1407 
1408     uint32_t driver_count = 0;
1409     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &driver_count, nullptr));
1410     ASSERT_EQ(driver_count, 1U);
1411 }
1412 
TEST(TryLoadWrongBinaries,WrongExplicit)1413 TEST(TryLoadWrongBinaries, WrongExplicit) {
1414     FrameworkEnvironment env{};
1415     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device("physical_device_0");
1416 
1417     const char* layer_name = "DummyLayerExplicit";
1418     env.add_fake_explicit_layer(
1419         ManifestLayer{}.add_layer(
1420             ManifestLayer::LayerDescription{}.set_name(layer_name).set_lib_path(CURRENT_PLATFORM_DUMMY_BINARY_WRONG_TYPE)),
1421         "dummy_test_layer.json");
1422 
1423     auto layer_props = env.GetLayerProperties(1);
1424     ASSERT_TRUE(string_eq(layer_name, layer_props[0].layerName));
1425 
1426     DebugUtilsLogger log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
1427     InstWrapper inst{env.vulkan_functions};
1428     inst.create_info.add_layer(layer_name);
1429     FillDebugUtilsCreateDetails(inst.create_info, log);
1430 
1431     // Explicit layer not found should generate a VK_ERROR_LAYER_NOT_PRESENT error message.
1432     inst.CheckCreate(VK_ERROR_LAYER_NOT_PRESENT);
1433 
1434     // Should get an error message for the explicit layer
1435 #if !defined(__APPLE__)
1436     ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name) + std::string("\" was wrong bit-type!")));
1437 #else   // __APPLE__
1438     // Apple only throws a wrong library type of error
1439     ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name) + std::string("\" failed to load!")));
1440 #endif  // __APPLE__
1441 }
1442 
TEST(TryLoadWrongBinaries,WrongImplicit)1443 TEST(TryLoadWrongBinaries, WrongImplicit) {
1444     FrameworkEnvironment env{};
1445     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device("physical_device_0");
1446 
1447     const char* layer_name = "DummyLayerImplicit0";
1448     env.add_fake_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
1449                                                               .set_name(layer_name)
1450                                                               .set_lib_path(CURRENT_PLATFORM_DUMMY_BINARY_WRONG_TYPE)
1451                                                               .set_disable_environment("DISABLE_ENV")),
1452                                 "dummy_test_layer.json");
1453 
1454     auto layer_props = env.GetLayerProperties(1);
1455     ASSERT_TRUE(string_eq(layer_name, layer_props[0].layerName));
1456 
1457     DebugUtilsLogger log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
1458     InstWrapper inst{env.vulkan_functions};
1459     FillDebugUtilsCreateDetails(inst.create_info, log);
1460 
1461     // We don't want to return VK_ERROR_LAYER_NOT_PRESENT for missing implicit layers because it's not the
1462     // application asking for them.
1463     inst.CheckCreate();
1464 
1465 #if !defined(__APPLE__)
1466     // Should get an info message for the bad implicit layer
1467     ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name) + std::string("\" was wrong bit-type.")));
1468 #else   // __APPLE__
1469     // Apple only throws a wrong library type of error
1470     ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name) + std::string("\" failed to load.")));
1471 #endif  // __APPLE__
1472 }
1473 
TEST(TryLoadWrongBinaries,WrongExplicitAndImplicit)1474 TEST(TryLoadWrongBinaries, WrongExplicitAndImplicit) {
1475     FrameworkEnvironment env{};
1476     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device("physical_device_0");
1477 
1478     const char* layer_name_0 = "DummyLayerExplicit";
1479     env.add_fake_explicit_layer(
1480         ManifestLayer{}.add_layer(
1481             ManifestLayer::LayerDescription{}.set_name(layer_name_0).set_lib_path(CURRENT_PLATFORM_DUMMY_BINARY_WRONG_TYPE)),
1482         "dummy_test_layer_0.json");
1483     const char* layer_name_1 = "DummyLayerImplicit";
1484     env.add_fake_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
1485                                                               .set_name(layer_name_1)
1486                                                               .set_lib_path(CURRENT_PLATFORM_DUMMY_BINARY_WRONG_TYPE)
1487                                                               .set_disable_environment("DISABLE_ENV")),
1488                                 "dummy_test_layer_1.json");
1489 
1490     auto layer_props = env.GetLayerProperties(2);
1491     ASSERT_TRUE(check_permutation({layer_name_0, layer_name_1}, layer_props));
1492 
1493     DebugUtilsLogger log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
1494     InstWrapper inst{env.vulkan_functions};
1495     inst.create_info.add_layer(layer_name_0);
1496     FillDebugUtilsCreateDetails(inst.create_info, log);
1497 
1498     // Explicit layer not found should generate a VK_ERROR_LAYER_NOT_PRESENT error message.
1499     inst.CheckCreate(VK_ERROR_LAYER_NOT_PRESENT);
1500 
1501 #if !defined(__APPLE__)
1502     // Should get error messages for both (the explicit is second and we don't want the implicit to return before the explicit
1503     // triggers a failure during vkCreateInstance)
1504     ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name_0) + std::string("\" was wrong bit-type!")));
1505     ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name_1) + std::string("\" was wrong bit-type.")));
1506 #else   // __APPLE__
1507     // Apple only throws a wrong library type of error
1508     ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name_0) + std::string("\" failed to load!")));
1509     ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name_1) + std::string("\" failed to load.")));
1510 #endif  // __APPLE__
1511 }
1512 
TEST(TryLoadWrongBinaries,WrongExplicitAndImplicitErrorOnly)1513 TEST(TryLoadWrongBinaries, WrongExplicitAndImplicitErrorOnly) {
1514     FrameworkEnvironment env{};
1515     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device("physical_device_0");
1516 
1517     const char* layer_name_0 = "DummyLayerExplicit";
1518     env.add_fake_explicit_layer(
1519         ManifestLayer{}.add_layer(
1520             ManifestLayer::LayerDescription{}.set_name(layer_name_0).set_lib_path(CURRENT_PLATFORM_DUMMY_BINARY_WRONG_TYPE)),
1521         "dummy_test_layer_0.json");
1522     const char* layer_name_1 = "DummyLayerImplicit";
1523     env.add_fake_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
1524                                                               .set_name(layer_name_1)
1525                                                               .set_lib_path(CURRENT_PLATFORM_DUMMY_BINARY_WRONG_TYPE)
1526                                                               .set_disable_environment("DISABLE_ENV")),
1527                                 "dummy_test_layer_1.json");
1528 
1529     auto layer_props = env.GetLayerProperties(2);
1530     ASSERT_TRUE(check_permutation({layer_name_0, layer_name_1}, layer_props));
1531 
1532     DebugUtilsLogger log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
1533     InstWrapper inst{env.vulkan_functions};
1534     inst.create_info.add_layer(layer_name_0);
1535     FillDebugUtilsCreateDetails(inst.create_info, log);
1536 
1537     // Explicit layer not found should generate a VK_ERROR_LAYER_NOT_PRESENT error message.
1538     inst.CheckCreate(VK_ERROR_LAYER_NOT_PRESENT);
1539 
1540 #if !defined(__APPLE__)
1541     // Should not get an error messages for either
1542     ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name_0) + std::string("\" was wrong bit-type!")));
1543     ASSERT_FALSE(log.find(std::string("Requested layer \"") + std::string(layer_name_1) + std::string("\" was wrong bit-type.")));
1544 #else   // __APPLE__
1545     // Apple only throws a wrong library type of error
1546     ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name_0) + std::string("\" failed to load!")));
1547     ASSERT_FALSE(log.find(std::string("Requested layer \"") + std::string(layer_name_1) + std::string("\" failed to load.")));
1548 #endif  // __APPLE__
1549 }
1550 
TEST(TryLoadWrongBinaries,BadExplicit)1551 TEST(TryLoadWrongBinaries, BadExplicit) {
1552     FrameworkEnvironment env{};
1553     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device("physical_device_0");
1554 
1555     const char* layer_name = "DummyLayerExplicit";
1556     env.add_fake_explicit_layer(
1557         ManifestLayer{}.add_layer(
1558             ManifestLayer::LayerDescription{}.set_name(layer_name).set_lib_path(CURRENT_PLATFORM_DUMMY_BINARY_BAD)),
1559         "dummy_test_layer.json");
1560 
1561     auto layer_props = env.GetLayerProperties(1);
1562     ASSERT_TRUE(string_eq(layer_name, layer_props[0].layerName));
1563 
1564     DebugUtilsLogger log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
1565     InstWrapper inst{env.vulkan_functions};
1566     inst.create_info.add_layer(layer_name);
1567     FillDebugUtilsCreateDetails(inst.create_info, log);
1568 
1569     // Explicit layer not found should generate a VK_ERROR_LAYER_NOT_PRESENT error message.
1570     inst.CheckCreate(VK_ERROR_LAYER_NOT_PRESENT);
1571 
1572     // Should get an error message for the bad explicit
1573     ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name) + std::string("\" failed to load!")));
1574 }
1575 
TEST(TryLoadWrongBinaries,BadImplicit)1576 TEST(TryLoadWrongBinaries, BadImplicit) {
1577     FrameworkEnvironment env{};
1578     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device("physical_device_0");
1579 
1580     const char* layer_name = "DummyLayerImplicit0";
1581     env.add_fake_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
1582                                                               .set_name(layer_name)
1583                                                               .set_lib_path(CURRENT_PLATFORM_DUMMY_BINARY_BAD)
1584                                                               .set_disable_environment("DISABLE_ENV")),
1585                                 "dummy_test_layer.json");
1586 
1587     auto layer_props = env.GetLayerProperties(1);
1588     ASSERT_TRUE(string_eq(layer_name, layer_props[0].layerName));
1589 
1590     DebugUtilsLogger log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
1591     InstWrapper inst{env.vulkan_functions};
1592     FillDebugUtilsCreateDetails(inst.create_info, log);
1593 
1594     // We don't want to return VK_ERROR_LAYER_NOT_PRESENT for missing implicit layers because it's not the
1595     // application asking for them.
1596     inst.CheckCreate();
1597 
1598     // Should get an info message for the bad implicit
1599     ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name) + std::string("\" failed to load.")));
1600 }
1601 
TEST(TryLoadWrongBinaries,BadExplicitAndImplicit)1602 TEST(TryLoadWrongBinaries, BadExplicitAndImplicit) {
1603     FrameworkEnvironment env{};
1604     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device("physical_device_0");
1605 
1606     const char* layer_name_0 = "DummyLayerExplicit";
1607     env.add_fake_explicit_layer(
1608         ManifestLayer{}.add_layer(
1609             ManifestLayer::LayerDescription{}.set_name(layer_name_0).set_lib_path(CURRENT_PLATFORM_DUMMY_BINARY_BAD)),
1610         "dummy_test_layer_0.json");
1611     const char* layer_name_1 = "DummyLayerImplicit0";
1612     env.add_fake_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
1613                                                               .set_name(layer_name_1)
1614                                                               .set_lib_path(CURRENT_PLATFORM_DUMMY_BINARY_BAD)
1615                                                               .set_disable_environment("DISABLE_ENV")),
1616                                 "dummy_test_layer_1.json");
1617 
1618     auto layer_props = env.GetLayerProperties(2);
1619     ASSERT_TRUE(check_permutation({layer_name_0, layer_name_1}, layer_props));
1620 
1621     DebugUtilsLogger log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
1622     InstWrapper inst{env.vulkan_functions};
1623     inst.create_info.add_layer(layer_name_0);
1624     FillDebugUtilsCreateDetails(inst.create_info, log);
1625 
1626     // Explicit layer not found should generate a VK_ERROR_LAYER_NOT_PRESENT error message.
1627     inst.CheckCreate(VK_ERROR_LAYER_NOT_PRESENT);
1628 
1629     // Apple only throws a wrong library type of error
1630     ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name_0) + std::string("\" failed to load!")));
1631     ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name_1) + std::string("\" failed to load.")));
1632 }
1633 
TEST(TryLoadWrongBinaries,WrongArchDriver)1634 TEST(TryLoadWrongBinaries, WrongArchDriver) {
1635     FrameworkEnvironment env{};
1636     // Intentionally set the wrong arch
1637     env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_2}.icd_manifest.set_library_arch(sizeof(void*) == 4 ? "64" : "32"))
1638         .add_physical_device("physical_device_0");
1639 
1640     DebugUtilsLogger log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
1641     InstWrapper inst{env.vulkan_functions};
1642     FillDebugUtilsCreateDetails(inst.create_info, log);
1643     inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER);
1644     ASSERT_TRUE(
1645         log.find("loader_parse_icd_manifest: Driver library architecture doesn't match the current running architecture, skipping "
1646                  "this driver"));
1647 }
1648 
TEST(TryLoadWrongBinaries,WrongArchLayer)1649 TEST(TryLoadWrongBinaries, WrongArchLayer) {
1650     FrameworkEnvironment env{};
1651     env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_2}).add_physical_device("physical_device_0");
1652 
1653     const char* layer_name = "TestLayer";
1654     env.add_explicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
1655                                                          .set_name(layer_name)
1656                                                          .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
1657                                                          // Intentionally set the wrong arch
1658                                                          .set_library_arch(sizeof(void*) == 4 ? "64" : "32")),
1659                            "test_layer.json");
1660 
1661     DebugUtilsLogger log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
1662     InstWrapper inst{env.vulkan_functions};
1663     FillDebugUtilsCreateDetails(inst.create_info, log);
1664     inst.create_info.add_layer(layer_name);
1665     inst.CheckCreate(VK_ERROR_LAYER_NOT_PRESENT);
1666     ASSERT_TRUE(log.find(std::string("The library architecture in layer ") + env.get_shimmed_layer_manifest_path(0).string() +
1667                          " doesn't match the current running architecture, skipping this layer"));
1668 }
1669 
TEST(EnumeratePhysicalDeviceGroups,OneCall)1670 TEST(EnumeratePhysicalDeviceGroups, OneCall) {
1671     FrameworkEnvironment env{};
1672     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1))
1673                        .set_min_icd_interface_version(5)
1674                        .set_icd_api_version(VK_API_VERSION_1_1)
1675                        .add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
1676 
1677     // ICD contains 3 devices in two groups
1678     for (size_t i = 0; i < 3; i++) {
1679         driver.physical_devices.emplace_back(std::string("physical_device_") + std::to_string(i));
1680         driver.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
1681         driver.physical_devices.back().properties.apiVersion = VK_API_VERSION_1_1;
1682     }
1683     driver.physical_device_groups.emplace_back(driver.physical_devices[0]);
1684     driver.physical_device_groups.back().use_physical_device(driver.physical_devices[1]);
1685     driver.physical_device_groups.emplace_back(driver.physical_devices[2]);
1686     const uint32_t max_physical_device_count = 3;
1687 
1688     // Core function
1689     {
1690         InstWrapper inst{env.vulkan_functions};
1691         inst.create_info.set_api_version(VK_API_VERSION_1_1);
1692         inst.CheckCreate();
1693 
1694         auto physical_devices = std::vector<VkPhysicalDevice>(max_physical_device_count);
1695         uint32_t returned_phys_dev_count = max_physical_device_count;
1696         ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &returned_phys_dev_count, physical_devices.data()));
1697         handle_assert_has_values(physical_devices);
1698 
1699         uint32_t group_count = static_cast<uint32_t>(driver.physical_device_groups.size());
1700         uint32_t returned_group_count = group_count;
1701         std::vector<VkPhysicalDeviceGroupProperties> group_props{};
1702         group_props.resize(group_count, VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
1703         ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props.data()));
1704         ASSERT_EQ(group_count, returned_group_count);
1705 
1706         // Make sure each physical device shows up in a group, but only once
1707         std::array<bool, max_physical_device_count> found{false};
1708         for (uint32_t group = 0; group < group_count; ++group) {
1709             for (uint32_t g_dev = 0; g_dev < group_props[group].physicalDeviceCount; ++g_dev) {
1710                 for (uint32_t dev = 0; dev < max_physical_device_count; ++dev) {
1711                     if (physical_devices[dev] == group_props[group].physicalDevices[g_dev]) {
1712                         ASSERT_EQ(false, found[dev]);
1713                         found[dev] = true;
1714                         break;
1715                     }
1716                 }
1717             }
1718         }
1719         for (uint32_t dev = 0; dev < max_physical_device_count; ++dev) {
1720             ASSERT_EQ(true, found[dev]);
1721         }
1722         for (auto& group : group_props) {
1723             VkDeviceGroupDeviceCreateInfo group_info{};
1724             group_info.sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO;
1725             group_info.physicalDeviceCount = group.physicalDeviceCount;
1726             group_info.pPhysicalDevices = &group.physicalDevices[0];
1727             VkBaseInStructure spacer_structure{};
1728             spacer_structure.sType = static_cast<VkStructureType>(100000);
1729             spacer_structure.pNext = reinterpret_cast<const VkBaseInStructure*>(&group_info);
1730             DeviceWrapper dev{inst};
1731             dev.create_info.dev.pNext = &spacer_structure;
1732             dev.CheckCreate(group.physicalDevices[0]);
1733 
1734             // This convoluted logic makes sure that the pNext chain is unmolested after being passed into vkCreateDevice
1735             // While not expected for applications to iterate over this chain, since it is const it is important to make sure
1736             // that the chain didn't change somehow, and especially so that iterating it doesn't crash.
1737             int count = 0;
1738             const VkBaseInStructure* pNext = reinterpret_cast<const VkBaseInStructure*>(dev.create_info.dev.pNext);
1739             while (pNext != nullptr) {
1740                 if (pNext->sType == VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO) {
1741                     ASSERT_EQ(&group_info, reinterpret_cast<const VkDeviceGroupDeviceCreateInfo*>(pNext));
1742                 }
1743                 if (pNext->sType == 100000) {
1744                     ASSERT_EQ(&spacer_structure, pNext);
1745                 }
1746                 pNext = pNext->pNext;
1747                 count++;
1748             }
1749             ASSERT_EQ(count, 2);
1750         }
1751     }
1752     driver.add_instance_extension({VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME});
1753     // Extension
1754     {
1755         InstWrapper inst{env.vulkan_functions};
1756         inst.create_info.add_extension(VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME);
1757         inst.CheckCreate();
1758 
1759         PFN_vkEnumeratePhysicalDeviceGroupsKHR vkEnumeratePhysicalDeviceGroupsKHR = inst.load("vkEnumeratePhysicalDeviceGroupsKHR");
1760 
1761         auto physical_devices = std::vector<VkPhysicalDevice>(max_physical_device_count);
1762         uint32_t returned_phys_dev_count = max_physical_device_count;
1763         ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &returned_phys_dev_count, physical_devices.data()));
1764         handle_assert_has_values(physical_devices);
1765 
1766         uint32_t group_count = static_cast<uint32_t>(driver.physical_device_groups.size());
1767         uint32_t returned_group_count = group_count;
1768         std::vector<VkPhysicalDeviceGroupProperties> group_props{};
1769         group_props.resize(group_count, VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
1770         ASSERT_EQ(VK_SUCCESS, vkEnumeratePhysicalDeviceGroupsKHR(inst, &returned_group_count, group_props.data()));
1771         ASSERT_EQ(group_count, returned_group_count);
1772 
1773         // Make sure each physical device shows up in a group, but only once
1774         std::array<bool, max_physical_device_count> found{false};
1775         for (uint32_t group = 0; group < group_count; ++group) {
1776             for (uint32_t g_dev = 0; g_dev < group_props[group].physicalDeviceCount; ++g_dev) {
1777                 for (uint32_t dev = 0; dev < max_physical_device_count; ++dev) {
1778                     if (physical_devices[dev] == group_props[group].physicalDevices[g_dev]) {
1779                         ASSERT_EQ(false, found[dev]);
1780                         found[dev] = true;
1781                         break;
1782                     }
1783                 }
1784             }
1785         }
1786         for (uint32_t dev = 0; dev < max_physical_device_count; ++dev) {
1787             ASSERT_EQ(true, found[dev]);
1788         }
1789         for (auto& group : group_props) {
1790             VkDeviceGroupDeviceCreateInfo group_info{};
1791             group_info.sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO;
1792             group_info.physicalDeviceCount = group.physicalDeviceCount;
1793             group_info.pPhysicalDevices = &group.physicalDevices[0];
1794             VkBaseInStructure spacer_structure{};
1795             spacer_structure.sType = static_cast<VkStructureType>(100000);
1796             spacer_structure.pNext = reinterpret_cast<const VkBaseInStructure*>(&group_info);
1797             DeviceWrapper dev{inst};
1798             dev.create_info.dev.pNext = &spacer_structure;
1799             dev.CheckCreate(group.physicalDevices[0]);
1800         }
1801     }
1802 }
1803 
TEST(EnumeratePhysicalDeviceGroups,TwoCall)1804 TEST(EnumeratePhysicalDeviceGroups, TwoCall) {
1805     FrameworkEnvironment env{};
1806     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1))
1807                        .set_min_icd_interface_version(5)
1808                        .set_icd_api_version(VK_API_VERSION_1_1)
1809                        .add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
1810 
1811     // ICD contains 3 devices in two groups
1812     for (size_t i = 0; i < 3; i++) {
1813         driver.physical_devices.emplace_back(std::string("physical_device_") + std::to_string(i));
1814         driver.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
1815         driver.physical_devices.back().properties.apiVersion = VK_API_VERSION_1_1;
1816     }
1817     driver.physical_device_groups.emplace_back(driver.physical_devices[0]);
1818     driver.physical_device_groups.back().use_physical_device(driver.physical_devices[1]);
1819     driver.physical_device_groups.emplace_back(driver.physical_devices[2]);
1820     const uint32_t max_physical_device_count = 3;
1821 
1822     // Core function
1823     {
1824         InstWrapper inst{env.vulkan_functions};
1825         inst.create_info.set_api_version(VK_API_VERSION_1_1);
1826         inst.CheckCreate();
1827 
1828         auto physical_devices = std::vector<VkPhysicalDevice>(max_physical_device_count);
1829         uint32_t returned_phys_dev_count = max_physical_device_count;
1830         ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &returned_phys_dev_count, physical_devices.data()));
1831         handle_assert_has_values(physical_devices);
1832 
1833         uint32_t group_count = static_cast<uint32_t>(driver.physical_device_groups.size());
1834         uint32_t returned_group_count = 0;
1835         ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, nullptr));
1836         ASSERT_EQ(group_count, returned_group_count);
1837 
1838         std::vector<VkPhysicalDeviceGroupProperties> group_props{};
1839         group_props.resize(group_count, VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
1840         ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props.data()));
1841         ASSERT_EQ(group_count, returned_group_count);
1842 
1843         // Make sure each physical device shows up in a group, but only once
1844         std::array<bool, max_physical_device_count> found{false};
1845         for (uint32_t group = 0; group < group_count; ++group) {
1846             for (uint32_t g_dev = 0; g_dev < group_props[group].physicalDeviceCount; ++g_dev) {
1847                 for (uint32_t dev = 0; dev < max_physical_device_count; ++dev) {
1848                     if (physical_devices[dev] == group_props[group].physicalDevices[g_dev]) {
1849                         ASSERT_EQ(false, found[dev]);
1850                         found[dev] = true;
1851                         break;
1852                     }
1853                 }
1854             }
1855         }
1856         for (uint32_t dev = 0; dev < max_physical_device_count; ++dev) {
1857             ASSERT_EQ(true, found[dev]);
1858         }
1859         for (auto& group : group_props) {
1860             VkDeviceGroupDeviceCreateInfo group_info{};
1861             group_info.sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO;
1862             group_info.physicalDeviceCount = group.physicalDeviceCount;
1863             group_info.pPhysicalDevices = &group.physicalDevices[0];
1864             DeviceWrapper dev{inst};
1865             dev.create_info.dev.pNext = &group_info;
1866             dev.CheckCreate(group.physicalDevices[0]);
1867         }
1868     }
1869     driver.add_instance_extension({VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME});
1870     // Extension
1871     {
1872         InstWrapper inst{env.vulkan_functions};
1873         inst.create_info.add_extension("VK_KHR_device_group_creation");
1874         inst.CheckCreate();
1875 
1876         auto physical_devices = std::vector<VkPhysicalDevice>(max_physical_device_count);
1877         uint32_t returned_phys_dev_count = max_physical_device_count;
1878         ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &returned_phys_dev_count, physical_devices.data()));
1879         handle_assert_has_values(physical_devices);
1880 
1881         PFN_vkEnumeratePhysicalDeviceGroupsKHR vkEnumeratePhysicalDeviceGroupsKHR = inst.load("vkEnumeratePhysicalDeviceGroupsKHR");
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, vkEnumeratePhysicalDeviceGroupsKHR(inst, &returned_group_count, nullptr));
1886         ASSERT_EQ(group_count, returned_group_count);
1887 
1888         std::vector<VkPhysicalDeviceGroupProperties> group_props{};
1889         group_props.resize(group_count, VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
1890         ASSERT_EQ(VK_SUCCESS, vkEnumeratePhysicalDeviceGroupsKHR(inst, &returned_group_count, group_props.data()));
1891         ASSERT_EQ(group_count, returned_group_count);
1892 
1893         // Make sure each physical device shows up in a group, but only once
1894         std::array<bool, max_physical_device_count> found{false};
1895         for (uint32_t group = 0; group < group_count; ++group) {
1896             for (uint32_t g_dev = 0; g_dev < group_props[group].physicalDeviceCount; ++g_dev) {
1897                 for (uint32_t dev = 0; dev < max_physical_device_count; ++dev) {
1898                     if (physical_devices[dev] == group_props[group].physicalDevices[g_dev]) {
1899                         ASSERT_EQ(false, found[dev]);
1900                         found[dev] = true;
1901                         break;
1902                     }
1903                 }
1904             }
1905         }
1906         for (uint32_t dev = 0; dev < max_physical_device_count; ++dev) {
1907             ASSERT_EQ(true, found[dev]);
1908         }
1909         for (auto& group : group_props) {
1910             VkDeviceGroupDeviceCreateInfo group_info{};
1911             group_info.sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO;
1912             group_info.physicalDeviceCount = group.physicalDeviceCount;
1913             group_info.pPhysicalDevices = &group.physicalDevices[0];
1914             DeviceWrapper dev{inst};
1915             dev.create_info.dev.pNext = &group_info;
1916             dev.CheckCreate(group.physicalDevices[0]);
1917         }
1918     }
1919 }
1920 
TEST(EnumeratePhysicalDeviceGroups,TwoCallIncomplete)1921 TEST(EnumeratePhysicalDeviceGroups, TwoCallIncomplete) {
1922     FrameworkEnvironment env{};
1923     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1))
1924                        .set_min_icd_interface_version(5)
1925                        .set_icd_api_version(VK_API_VERSION_1_1)
1926                        .add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
1927 
1928     // ICD contains 3 devices in two groups
1929     for (size_t i = 0; i < 3; i++) {
1930         driver.physical_devices.emplace_back(std::string("physical_device_") + std::to_string(i));
1931         driver.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
1932         driver.physical_devices.back().properties.apiVersion = VK_API_VERSION_1_1;
1933     }
1934     driver.physical_device_groups.emplace_back(driver.physical_devices[0]);
1935     driver.physical_device_groups.back().use_physical_device(driver.physical_devices[1]);
1936     driver.physical_device_groups.emplace_back(driver.physical_devices[2]);
1937 
1938     // Core function
1939     {
1940         InstWrapper inst{env.vulkan_functions};
1941         inst.create_info.set_api_version(VK_API_VERSION_1_1);
1942         inst.CheckCreate();
1943 
1944         uint32_t group_count = static_cast<uint32_t>(driver.physical_device_groups.size());
1945         uint32_t returned_group_count = 0;
1946         ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, nullptr));
1947         ASSERT_EQ(group_count, returned_group_count);
1948 
1949         returned_group_count = 1;
1950         std::array<VkPhysicalDeviceGroupProperties, 1> group_props{};
1951         group_props[0].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES;
1952         ASSERT_EQ(VK_INCOMPLETE, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props.data()));
1953         ASSERT_EQ(1U, returned_group_count);
1954 
1955         returned_group_count = 2;
1956         std::array<VkPhysicalDeviceGroupProperties, 2> group_props_2{};
1957         group_props_2[0].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES;
1958         group_props_2[1].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES;
1959         ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props_2.data()));
1960         ASSERT_EQ(2U, returned_group_count);
1961 
1962         ASSERT_EQ(group_props[0].physicalDeviceCount, group_props_2[0].physicalDeviceCount);
1963         ASSERT_EQ(group_props[0].physicalDevices[0], group_props_2[0].physicalDevices[0]);
1964         ASSERT_EQ(group_props[0].physicalDevices[1], group_props_2[0].physicalDevices[1]);
1965 
1966         for (auto& group : group_props) {
1967             VkDeviceGroupDeviceCreateInfo group_info{};
1968             group_info.sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO;
1969             group_info.physicalDeviceCount = group.physicalDeviceCount;
1970             group_info.pPhysicalDevices = &group.physicalDevices[0];
1971             DeviceWrapper dev{inst};
1972             dev.create_info.dev.pNext = &group_info;
1973             dev.CheckCreate(group.physicalDevices[0]);
1974         }
1975     }
1976     driver.add_instance_extension({VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME});
1977     // Extension
1978     {
1979         InstWrapper inst{env.vulkan_functions};
1980         inst.create_info.add_extension("VK_KHR_device_group_creation");
1981         inst.CheckCreate();
1982 
1983         PFN_vkEnumeratePhysicalDeviceGroupsKHR vkEnumeratePhysicalDeviceGroupsKHR = inst.load("vkEnumeratePhysicalDeviceGroupsKHR");
1984 
1985         uint32_t group_count = static_cast<uint32_t>(driver.physical_device_groups.size());
1986         uint32_t returned_group_count = 0;
1987         ASSERT_EQ(VK_SUCCESS, vkEnumeratePhysicalDeviceGroupsKHR(inst, &returned_group_count, nullptr));
1988         ASSERT_EQ(group_count, returned_group_count);
1989 
1990         returned_group_count = 1;
1991         std::array<VkPhysicalDeviceGroupProperties, 1> group_props{};
1992         group_props[0].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES;
1993         ASSERT_EQ(VK_INCOMPLETE, vkEnumeratePhysicalDeviceGroupsKHR(inst, &returned_group_count, group_props.data()));
1994         ASSERT_EQ(1U, returned_group_count);
1995 
1996         returned_group_count = 2;
1997         std::array<VkPhysicalDeviceGroupProperties, 2> group_props_2{};
1998         group_props_2[0].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES;
1999         group_props_2[1].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES;
2000         ASSERT_EQ(VK_SUCCESS, vkEnumeratePhysicalDeviceGroupsKHR(inst, &returned_group_count, group_props_2.data()));
2001         ASSERT_EQ(2U, returned_group_count);
2002 
2003         ASSERT_EQ(group_props[0].physicalDeviceCount, group_props_2[0].physicalDeviceCount);
2004         ASSERT_EQ(group_props[0].physicalDevices[0], group_props_2[0].physicalDevices[0]);
2005         ASSERT_EQ(group_props[0].physicalDevices[1], group_props_2[0].physicalDevices[1]);
2006 
2007         for (auto& group : group_props) {
2008             VkDeviceGroupDeviceCreateInfo group_info{};
2009             group_info.sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO;
2010             group_info.physicalDeviceCount = group.physicalDeviceCount;
2011             group_info.pPhysicalDevices = &group.physicalDevices[0];
2012             DeviceWrapper dev{inst};
2013             dev.create_info.dev.pNext = &group_info;
2014             dev.CheckCreate(group.physicalDevices[0]);
2015         }
2016     }
2017 }
2018 
2019 // Call the core vkEnumeratePhysicalDeviceGroups and the extension
2020 // vkEnumeratePhysicalDeviceGroupsKHR, and make sure they return the same info.
TEST(EnumeratePhysicalDeviceGroups,TestCoreVersusExtensionSameReturns)2021 TEST(EnumeratePhysicalDeviceGroups, TestCoreVersusExtensionSameReturns) {
2022     FrameworkEnvironment env{};
2023     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1))
2024                        .set_min_icd_interface_version(5)
2025                        .set_icd_api_version(VK_API_VERSION_1_1)
2026                        .add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME})
2027                        .add_instance_extension({VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME});
2028 
2029     // Generate the devices
2030     for (size_t i = 0; i < 6; i++) {
2031         driver.physical_devices.emplace_back(std::string("physical_device_") + std::to_string(i));
2032         driver.physical_devices.back().properties.apiVersion = VK_API_VERSION_1_1;
2033     }
2034 
2035     // Generate the starting groups
2036     driver.physical_device_groups.emplace_back(driver.physical_devices[0]);
2037     driver.physical_device_groups.emplace_back(driver.physical_devices[1]);
2038     driver.physical_device_groups.back()
2039         .use_physical_device(driver.physical_devices[2])
2040         .use_physical_device(driver.physical_devices[3]);
2041     driver.physical_device_groups.emplace_back(driver.physical_devices[4]);
2042     driver.physical_device_groups.back().use_physical_device(driver.physical_devices[5]);
2043 
2044     uint32_t expected_counts[3] = {1, 3, 2};
2045     uint32_t core_group_count = 0;
2046     std::vector<VkPhysicalDeviceGroupProperties> core_group_props{};
2047     uint32_t ext_group_count = 0;
2048     std::vector<VkPhysicalDeviceGroupProperties> ext_group_props{};
2049 
2050     InstWrapper inst{env.vulkan_functions};
2051     inst.create_info.set_api_version(1, 1, 0);
2052     inst.create_info.add_extension("VK_KHR_device_group_creation");
2053     inst.CheckCreate();
2054 
2055     // Core function
2056     core_group_count = static_cast<uint32_t>(driver.physical_device_groups.size());
2057     uint32_t returned_group_count = 0;
2058     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, nullptr));
2059     ASSERT_EQ(core_group_count, returned_group_count);
2060 
2061     core_group_props.resize(returned_group_count,
2062                             VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
2063     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, core_group_props.data()));
2064     ASSERT_EQ(core_group_count, returned_group_count);
2065 
2066     PFN_vkEnumeratePhysicalDeviceGroupsKHR vkEnumeratePhysicalDeviceGroupsKHR = inst.load("vkEnumeratePhysicalDeviceGroupsKHR");
2067 
2068     ext_group_count = static_cast<uint32_t>(driver.physical_device_groups.size());
2069     returned_group_count = 0;
2070     ASSERT_EQ(VK_SUCCESS, vkEnumeratePhysicalDeviceGroupsKHR(inst, &returned_group_count, nullptr));
2071     ASSERT_EQ(ext_group_count, returned_group_count);
2072 
2073     ext_group_props.resize(returned_group_count,
2074                            VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
2075     ASSERT_EQ(VK_SUCCESS, vkEnumeratePhysicalDeviceGroupsKHR(inst, &returned_group_count, ext_group_props.data()));
2076     ASSERT_EQ(ext_group_count, returned_group_count);
2077 
2078     // Make sure data from each matches
2079     ASSERT_EQ(core_group_count, 3U);
2080     ASSERT_EQ(ext_group_count, 3U);
2081     for (uint32_t group = 0; group < core_group_count; ++group) {
2082         ASSERT_EQ(core_group_props[group].physicalDeviceCount, expected_counts[group]);
2083         ASSERT_EQ(ext_group_props[group].physicalDeviceCount, expected_counts[group]);
2084         for (uint32_t dev = 0; dev < core_group_props[group].physicalDeviceCount; ++dev) {
2085             ASSERT_EQ(core_group_props[group].physicalDevices[dev], ext_group_props[group].physicalDevices[dev]);
2086         }
2087     }
2088     // Make sure no physical device appears in more than one group
2089     for (uint32_t group1 = 0; group1 < core_group_count; ++group1) {
2090         for (uint32_t group2 = group1 + 1; group2 < core_group_count; ++group2) {
2091             for (uint32_t dev1 = 0; dev1 < core_group_props[group1].physicalDeviceCount; ++dev1) {
2092                 for (uint32_t dev2 = 0; dev2 < core_group_props[group1].physicalDeviceCount; ++dev2) {
2093                     ASSERT_NE(core_group_props[group1].physicalDevices[dev1], core_group_props[group2].physicalDevices[dev2]);
2094                 }
2095             }
2096         }
2097     }
2098     for (auto& group : core_group_props) {
2099         VkDeviceGroupDeviceCreateInfo group_info{};
2100         group_info.sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO;
2101         group_info.physicalDeviceCount = group.physicalDeviceCount;
2102         group_info.pPhysicalDevices = &group.physicalDevices[0];
2103         DeviceWrapper dev{inst};
2104         dev.create_info.dev.pNext = &group_info;
2105         dev.CheckCreate(group.physicalDevices[0]);
2106     }
2107 }
2108 
2109 // Start with 6 devices in 3 different groups, and then add a group,
2110 // querying vkEnumeratePhysicalDeviceGroups before and after the add.
TEST(EnumeratePhysicalDeviceGroups,CallThriceAddGroupInBetween)2111 TEST(EnumeratePhysicalDeviceGroups, CallThriceAddGroupInBetween) {
2112     FrameworkEnvironment env{};
2113     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1))
2114                        .set_min_icd_interface_version(5)
2115                        .set_icd_api_version(VK_API_VERSION_1_1);
2116 
2117     // Generate the devices
2118     for (size_t i = 0; i < 7; i++) {
2119         driver.physical_devices.emplace_back(std::string("physical_device_") + std::to_string(i));
2120         driver.physical_devices.back().properties.apiVersion = VK_API_VERSION_1_1;
2121     }
2122 
2123     // Generate the starting groups
2124     driver.physical_device_groups.emplace_back(driver.physical_devices[0]);
2125     driver.physical_device_groups.emplace_back(driver.physical_devices[1]);
2126     driver.physical_device_groups.back()
2127         .use_physical_device(driver.physical_devices[2])
2128         .use_physical_device(driver.physical_devices[3]);
2129     driver.physical_device_groups.emplace_back(driver.physical_devices[4]);
2130     driver.physical_device_groups.back().use_physical_device(driver.physical_devices[5]);
2131 
2132     uint32_t before_expected_counts[3] = {1, 3, 2};
2133     uint32_t after_expected_counts[4] = {1, 3, 1, 2};
2134     uint32_t before_group_count = 3;
2135     uint32_t after_group_count = 4;
2136     uint32_t returned_group_count = 0;
2137 
2138     InstWrapper inst{env.vulkan_functions};
2139     inst.create_info.set_api_version(1, 1, 0);
2140     inst.CheckCreate();
2141 
2142     std::vector<VkPhysicalDeviceGroupProperties> group_props_before{};
2143     group_props_before.resize(before_group_count,
2144                               VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
2145     returned_group_count = before_group_count;
2146     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props_before.data()));
2147     ASSERT_EQ(before_group_count, returned_group_count);
2148     for (uint32_t group = 0; group < before_group_count; ++group) {
2149         ASSERT_EQ(group_props_before[group].physicalDeviceCount, before_expected_counts[group]);
2150     }
2151 
2152     // Insert new group after first two
2153     driver.physical_device_groups.insert(driver.physical_device_groups.begin() + 2, driver.physical_devices[6]);
2154 
2155     std::vector<VkPhysicalDeviceGroupProperties> group_props_after{};
2156     group_props_after.resize(before_group_count,
2157                              VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
2158     ASSERT_EQ(VK_INCOMPLETE, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props_after.data()));
2159     ASSERT_EQ(before_group_count, returned_group_count);
2160     for (uint32_t group = 0; group < before_group_count; ++group) {
2161         ASSERT_EQ(group_props_after[group].physicalDeviceCount, after_expected_counts[group]);
2162     }
2163 
2164     group_props_after.resize(after_group_count,
2165                              VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
2166     returned_group_count = after_group_count;
2167     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props_after.data()));
2168     ASSERT_EQ(after_group_count, returned_group_count);
2169     for (uint32_t group = 0; group < after_group_count; ++group) {
2170         ASSERT_EQ(group_props_after[group].physicalDeviceCount, after_expected_counts[group]);
2171     }
2172 
2173     // Make sure all devices in the old group info are still found in the new group info
2174     for (uint32_t group1 = 0; group1 < group_props_before.size(); ++group1) {
2175         for (uint32_t group2 = 0; group2 < group_props_after.size(); ++group2) {
2176             if (group_props_before[group1].physicalDeviceCount == group_props_after[group2].physicalDeviceCount) {
2177                 uint32_t found_count = 0;
2178                 bool found = false;
2179                 for (uint32_t dev1 = 0; dev1 < group_props_before[group1].physicalDeviceCount; ++dev1) {
2180                     found = false;
2181                     for (uint32_t dev2 = 0; dev2 < group_props_after[group2].physicalDeviceCount; ++dev2) {
2182                         if (group_props_before[group1].physicalDevices[dev1] == group_props_after[group2].physicalDevices[dev2]) {
2183                             found_count++;
2184                             found = true;
2185                             break;
2186                         }
2187                     }
2188                 }
2189                 ASSERT_EQ(found, found_count == group_props_before[group1].physicalDeviceCount);
2190             }
2191         }
2192     }
2193     for (auto& group : group_props_after) {
2194         VkDeviceGroupDeviceCreateInfo group_info{};
2195         group_info.sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO;
2196         group_info.physicalDeviceCount = group.physicalDeviceCount;
2197         group_info.pPhysicalDevices = &group.physicalDevices[0];
2198         DeviceWrapper dev{inst};
2199         dev.create_info.dev.pNext = &group_info;
2200         dev.CheckCreate(group.physicalDevices[0]);
2201     }
2202 }
2203 
2204 // Start with 7 devices in 4 different groups, and then remove a group,
2205 // querying vkEnumeratePhysicalDeviceGroups before and after the remove.
TEST(EnumeratePhysicalDeviceGroups,CallTwiceRemoveGroupInBetween)2206 TEST(EnumeratePhysicalDeviceGroups, CallTwiceRemoveGroupInBetween) {
2207     FrameworkEnvironment env{};
2208     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1))
2209                        .set_min_icd_interface_version(5)
2210                        .set_icd_api_version(VK_API_VERSION_1_1);
2211 
2212     // Generate the devices
2213     for (size_t i = 0; i < 7; i++) {
2214         driver.physical_devices.emplace_back(std::string("physical_device_") + std::to_string(i));
2215         driver.physical_devices.back().properties.apiVersion = VK_API_VERSION_1_1;
2216     }
2217 
2218     // Generate the starting groups
2219     driver.physical_device_groups.emplace_back(driver.physical_devices[0]);
2220     driver.physical_device_groups.emplace_back(driver.physical_devices[1]);
2221     driver.physical_device_groups.back()
2222         .use_physical_device(driver.physical_devices[2])
2223         .use_physical_device(driver.physical_devices[3]);
2224     driver.physical_device_groups.emplace_back(driver.physical_devices[4]);
2225     driver.physical_device_groups.emplace_back(driver.physical_devices[5]);
2226     driver.physical_device_groups.back().use_physical_device(driver.physical_devices[6]);
2227 
2228     uint32_t before_expected_counts[4] = {1, 3, 1, 2};
2229     uint32_t after_expected_counts[3] = {1, 3, 2};
2230     uint32_t before_group_count = 4;
2231     uint32_t after_group_count = 3;
2232     uint32_t returned_group_count = 0;
2233 
2234     InstWrapper inst{env.vulkan_functions};
2235     inst.create_info.set_api_version(1, 1, 0);
2236     inst.CheckCreate();
2237 
2238     std::vector<VkPhysicalDeviceGroupProperties> group_props_before{};
2239     group_props_before.resize(before_group_count,
2240                               VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
2241     returned_group_count = before_group_count;
2242     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props_before.data()));
2243     ASSERT_EQ(before_group_count, returned_group_count);
2244     for (uint32_t group = 0; group < before_group_count; ++group) {
2245         ASSERT_EQ(group_props_before[group].physicalDeviceCount, before_expected_counts[group]);
2246     }
2247 
2248     // Insert new group after first two
2249     driver.physical_device_groups.erase(driver.physical_device_groups.begin() + 2);
2250 
2251     std::vector<VkPhysicalDeviceGroupProperties> group_props_after{};
2252     group_props_after.resize(after_group_count,
2253                              VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
2254     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props_after.data()));
2255     ASSERT_EQ(after_group_count, returned_group_count);
2256     for (uint32_t group = 0; group < after_group_count; ++group) {
2257         ASSERT_EQ(group_props_after[group].physicalDeviceCount, after_expected_counts[group]);
2258     }
2259 
2260     // Make sure all devices in the new group info are found in the old group info
2261     for (uint32_t group1 = 0; group1 < group_props_after.size(); ++group1) {
2262         for (uint32_t group2 = 0; group2 < group_props_before.size(); ++group2) {
2263             if (group_props_after[group1].physicalDeviceCount == group_props_before[group2].physicalDeviceCount) {
2264                 uint32_t found_count = 0;
2265                 bool found = false;
2266                 for (uint32_t dev1 = 0; dev1 < group_props_after[group1].physicalDeviceCount; ++dev1) {
2267                     found = false;
2268                     for (uint32_t dev2 = 0; dev2 < group_props_before[group2].physicalDeviceCount; ++dev2) {
2269                         if (group_props_after[group1].physicalDevices[dev1] == group_props_before[group2].physicalDevices[dev2]) {
2270                             found_count++;
2271                             found = true;
2272                             break;
2273                         }
2274                     }
2275                 }
2276                 ASSERT_EQ(found, found_count == group_props_after[group1].physicalDeviceCount);
2277             }
2278         }
2279     }
2280     for (auto& group : group_props_after) {
2281         VkDeviceGroupDeviceCreateInfo group_info{};
2282         group_info.sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO;
2283         group_info.physicalDeviceCount = group.physicalDeviceCount;
2284         group_info.pPhysicalDevices = &group.physicalDevices[0];
2285         DeviceWrapper dev{inst};
2286         dev.create_info.dev.pNext = &group_info;
2287         dev.CheckCreate(group.physicalDevices[0]);
2288     }
2289 }
2290 
2291 // Start with 6 devices in 3 different groups, and then add a device to the middle group,
2292 // querying vkEnumeratePhysicalDeviceGroups before and after the add.
TEST(EnumeratePhysicalDeviceGroups,CallTwiceAddDeviceInBetween)2293 TEST(EnumeratePhysicalDeviceGroups, CallTwiceAddDeviceInBetween) {
2294     FrameworkEnvironment env{};
2295     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1))
2296                        .set_min_icd_interface_version(5)
2297                        .set_icd_api_version(VK_API_VERSION_1_1);
2298 
2299     // Generate the devices
2300     for (size_t i = 0; i < 7; i++) {
2301         driver.physical_devices.emplace_back(std::string("physical_device_") + std::to_string(i));
2302         driver.physical_devices.back().properties.apiVersion = VK_API_VERSION_1_1;
2303     }
2304 
2305     // Generate the starting groups
2306     driver.physical_device_groups.emplace_back(driver.physical_devices[0]);
2307     driver.physical_device_groups.emplace_back(driver.physical_devices[1]);
2308     driver.physical_device_groups.back()
2309         .use_physical_device(driver.physical_devices[2])
2310         .use_physical_device(driver.physical_devices[3]);
2311     driver.physical_device_groups.emplace_back(driver.physical_devices[4]);
2312     driver.physical_device_groups.back().use_physical_device(driver.physical_devices[5]);
2313 
2314     uint32_t expected_group_count = 3;
2315     uint32_t before_expected_counts[3] = {1, 3, 2};
2316     uint32_t after_expected_counts[3] = {1, 4, 2};
2317     uint32_t returned_group_count = 0;
2318 
2319     InstWrapper inst{env.vulkan_functions};
2320     inst.create_info.set_api_version(1, 1, 0);
2321     inst.CheckCreate();
2322 
2323     std::vector<VkPhysicalDeviceGroupProperties> group_props_before{};
2324     group_props_before.resize(expected_group_count,
2325                               VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
2326     returned_group_count = expected_group_count;
2327     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props_before.data()));
2328     ASSERT_EQ(expected_group_count, returned_group_count);
2329     for (uint32_t group = 0; group < expected_group_count; ++group) {
2330         ASSERT_EQ(group_props_before[group].physicalDeviceCount, before_expected_counts[group]);
2331     }
2332 
2333     // Insert new device to 2nd group
2334     driver.physical_device_groups[1].use_physical_device(driver.physical_devices[6]);
2335 
2336     std::vector<VkPhysicalDeviceGroupProperties> group_props_after{};
2337     group_props_after.resize(expected_group_count,
2338                              VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
2339     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props_after.data()));
2340     ASSERT_EQ(expected_group_count, returned_group_count);
2341     for (uint32_t group = 0; group < expected_group_count; ++group) {
2342         ASSERT_EQ(group_props_after[group].physicalDeviceCount, after_expected_counts[group]);
2343     }
2344 
2345     // Make sure all devices in the old group info are still found in the new group info
2346     for (uint32_t group1 = 0; group1 < group_props_before.size(); ++group1) {
2347         for (uint32_t group2 = 0; group2 < group_props_after.size(); ++group2) {
2348             uint32_t found_count = 0;
2349             bool found = false;
2350             for (uint32_t dev1 = 0; dev1 < group_props_before[group1].physicalDeviceCount; ++dev1) {
2351                 found = false;
2352                 for (uint32_t dev2 = 0; dev2 < group_props_after[group2].physicalDeviceCount; ++dev2) {
2353                     if (group_props_before[group1].physicalDevices[dev1] == group_props_after[group2].physicalDevices[dev2]) {
2354                         found_count++;
2355                         found = true;
2356                         break;
2357                     }
2358                 }
2359             }
2360             ASSERT_EQ(found, found_count != 0 && found_count == before_expected_counts[group1]);
2361             if (found) {
2362                 break;
2363             }
2364         }
2365     }
2366     for (auto& group : group_props_after) {
2367         VkDeviceGroupDeviceCreateInfo group_info{};
2368         group_info.sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO;
2369         group_info.physicalDeviceCount = group.physicalDeviceCount;
2370         group_info.pPhysicalDevices = &group.physicalDevices[0];
2371         DeviceWrapper dev{inst};
2372         dev.create_info.dev.pNext = &group_info;
2373         dev.CheckCreate(group.physicalDevices[0]);
2374     }
2375 }
2376 
2377 // Start with 6 devices in 3 different groups, and then remove a device to the middle group,
2378 // querying vkEnumeratePhysicalDeviceGroups before and after the remove.
TEST(EnumeratePhysicalDeviceGroups,CallTwiceRemoveDeviceInBetween)2379 TEST(EnumeratePhysicalDeviceGroups, CallTwiceRemoveDeviceInBetween) {
2380     FrameworkEnvironment env{};
2381     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1))
2382                        .set_min_icd_interface_version(5)
2383                        .set_icd_api_version(VK_API_VERSION_1_1);
2384 
2385     // Generate the devices
2386     for (size_t i = 0; i < 6; i++) {
2387         driver.physical_devices.emplace_back(std::string("physical_device_") + std::to_string(i));
2388         driver.physical_devices.back().properties.apiVersion = VK_API_VERSION_1_1;
2389     }
2390 
2391     // Generate the starting groups
2392     driver.physical_device_groups.emplace_back(driver.physical_devices[0]);
2393     driver.physical_device_groups.emplace_back(driver.physical_devices[1]);
2394     driver.physical_device_groups.back()
2395         .use_physical_device(driver.physical_devices[2])
2396         .use_physical_device(driver.physical_devices[3]);
2397     driver.physical_device_groups.emplace_back(driver.physical_devices[4]);
2398     driver.physical_device_groups.back().use_physical_device(driver.physical_devices[5]);
2399 
2400     uint32_t before_expected_counts[3] = {1, 3, 2};
2401     uint32_t after_expected_counts[3] = {1, 2, 2};
2402     uint32_t expected_group_count = 3;
2403     uint32_t returned_group_count = 0;
2404 
2405     InstWrapper inst{env.vulkan_functions};
2406     inst.create_info.set_api_version(1, 1, 0);
2407     inst.CheckCreate();
2408 
2409     std::vector<VkPhysicalDeviceGroupProperties> group_props_before{};
2410     group_props_before.resize(expected_group_count,
2411                               VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
2412     returned_group_count = expected_group_count;
2413     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props_before.data()));
2414     ASSERT_EQ(expected_group_count, returned_group_count);
2415     printf("Before:\n");
2416     for (uint32_t group = 0; group < expected_group_count; ++group) {
2417         printf("  Group %u:\n", group);
2418         ASSERT_EQ(group_props_before[group].physicalDeviceCount, before_expected_counts[group]);
2419         for (uint32_t dev = 0; dev < group_props_before[group].physicalDeviceCount; ++dev) {
2420             printf("    Dev %u: %p\n", dev, group_props_before[group].physicalDevices[dev]);
2421         }
2422     }
2423 
2424     // Remove middle device in middle group
2425     driver.physical_device_groups[1].physical_device_handles.erase(
2426         driver.physical_device_groups[1].physical_device_handles.begin() + 1);
2427 
2428     std::vector<VkPhysicalDeviceGroupProperties> group_props_after{};
2429     group_props_after.resize(expected_group_count,
2430                              VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
2431     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props_after.data()));
2432     ASSERT_EQ(expected_group_count, returned_group_count);
2433     printf("After:\n");
2434     for (uint32_t group = 0; group < expected_group_count; ++group) {
2435         printf("  Group %u:\n", group);
2436         ASSERT_EQ(group_props_after[group].physicalDeviceCount, after_expected_counts[group]);
2437         for (uint32_t dev = 0; dev < group_props_after[group].physicalDeviceCount; ++dev) {
2438             printf("    Dev %u: %p\n", dev, group_props_after[group].physicalDevices[dev]);
2439         }
2440     }
2441 
2442     // Make sure all devices in the new group info are found in the old group info
2443     for (uint32_t group1 = 0; group1 < group_props_after.size(); ++group1) {
2444         for (uint32_t group2 = 0; group2 < group_props_before.size(); ++group2) {
2445             uint32_t found_count = 0;
2446             bool found = false;
2447             for (uint32_t dev1 = 0; dev1 < group_props_after[group1].physicalDeviceCount; ++dev1) {
2448                 found = false;
2449                 for (uint32_t dev2 = 0; dev2 < group_props_before[group2].physicalDeviceCount; ++dev2) {
2450                     if (group_props_after[group1].physicalDevices[dev1] == group_props_before[group2].physicalDevices[dev2]) {
2451                         found_count++;
2452                         found = true;
2453                         break;
2454                     }
2455                 }
2456             }
2457             ASSERT_EQ(found, found_count != 0 && found_count == after_expected_counts[group1]);
2458             if (found) {
2459                 break;
2460             }
2461         }
2462     }
2463     for (auto& group : group_props_after) {
2464         VkDeviceGroupDeviceCreateInfo group_info{};
2465         group_info.sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO;
2466         group_info.physicalDeviceCount = group.physicalDeviceCount;
2467         group_info.pPhysicalDevices = &group.physicalDevices[0];
2468         DeviceWrapper dev{inst};
2469         dev.create_info.dev.pNext = &group_info;
2470         dev.CheckCreate(group.physicalDevices[0]);
2471     }
2472 }
2473 
2474 // Start with 9 devices but only some in 3 different groups, add and remove
2475 // various devices and groups while querying in between.
TEST(EnumeratePhysicalDeviceGroups,MultipleAddRemoves)2476 TEST(EnumeratePhysicalDeviceGroups, MultipleAddRemoves) {
2477     FrameworkEnvironment env{};
2478     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1))
2479                        .set_min_icd_interface_version(5)
2480                        .set_icd_api_version(VK_API_VERSION_1_1);
2481 
2482     // Generate the devices
2483     for (size_t i = 0; i < 9; i++) {
2484         driver.physical_devices.emplace_back(std::string("physical_device_") + std::to_string(i));
2485         driver.physical_devices.back().properties.apiVersion = VK_API_VERSION_1_1;
2486     }
2487 
2488     // Generate the starting groups
2489     driver.physical_device_groups.emplace_back(driver.physical_devices[0]);
2490     driver.physical_device_groups.emplace_back(driver.physical_devices[1]);
2491     driver.physical_device_groups.back()
2492         .use_physical_device(driver.physical_devices[2])
2493         .use_physical_device(driver.physical_devices[3]);
2494     driver.physical_device_groups.emplace_back(driver.physical_devices[4]);
2495     driver.physical_device_groups.back().use_physical_device(driver.physical_devices[5]);
2496 
2497     uint32_t before_expected_counts[3] = {1, 3, 2};
2498     uint32_t after_add_group_expected_counts[4] = {1, 3, 1, 2};
2499     uint32_t after_remove_dev_expected_counts[4] = {1, 2, 1, 2};
2500     uint32_t after_remove_group_expected_counts[3] = {2, 1, 2};
2501     uint32_t after_add_dev_expected_counts[3] = {2, 1, 4};
2502     uint32_t before_group_count = 3;
2503     uint32_t after_group_count = 4;
2504     uint32_t returned_group_count = 0;
2505 
2506     InstWrapper inst{env.vulkan_functions};
2507     inst.create_info.set_api_version(1, 1, 0);
2508     inst.CheckCreate();
2509 
2510     // Should be: 3 Groups { { 0 }, { 1, 2, 3 }, { 4, 5 } }
2511     std::vector<VkPhysicalDeviceGroupProperties> group_props_before{};
2512     group_props_before.resize(before_group_count,
2513                               VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
2514     returned_group_count = before_group_count;
2515     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props_before.data()));
2516     ASSERT_EQ(before_group_count, returned_group_count);
2517     for (uint32_t group = 0; group < before_group_count; ++group) {
2518         ASSERT_EQ(group_props_before[group].physicalDeviceCount, before_expected_counts[group]);
2519     }
2520 
2521     // Insert new group after first two
2522     driver.physical_device_groups.insert(driver.physical_device_groups.begin() + 2, driver.physical_devices[6]);
2523 
2524     // Should be: 4 Groups { { 0 }, { 1, 2, 3 }, { 6 }, { 4, 5 } }
2525     std::vector<VkPhysicalDeviceGroupProperties> group_props_after_add_group{};
2526     group_props_after_add_group.resize(after_group_count,
2527                                        VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
2528     returned_group_count = after_group_count;
2529     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props_after_add_group.data()));
2530     ASSERT_EQ(after_group_count, returned_group_count);
2531     for (uint32_t group = 0; group < before_group_count; ++group) {
2532         ASSERT_EQ(group_props_after_add_group[group].physicalDeviceCount, after_add_group_expected_counts[group]);
2533     }
2534 
2535     // Remove first device in 2nd group
2536     driver.physical_device_groups[1].physical_device_handles.erase(
2537         driver.physical_device_groups[1].physical_device_handles.begin());
2538 
2539     // Should be: 4 Groups { { 0 }, { 2, 3 }, { 6 }, { 4, 5 } }
2540     std::vector<VkPhysicalDeviceGroupProperties> group_props_after_remove_device{};
2541     group_props_after_remove_device.resize(after_group_count,
2542                                            VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
2543     returned_group_count = after_group_count;
2544     ASSERT_EQ(VK_SUCCESS,
2545               inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props_after_remove_device.data()));
2546     ASSERT_EQ(after_group_count, returned_group_count);
2547     for (uint32_t group = 0; group < before_group_count; ++group) {
2548         ASSERT_EQ(group_props_after_remove_device[group].physicalDeviceCount, after_remove_dev_expected_counts[group]);
2549     }
2550 
2551     // Remove first group
2552     driver.physical_device_groups.erase(driver.physical_device_groups.begin());
2553 
2554     // Should be: 3 Groups { { 2, 3 }, { 6 }, { 4, 5 } }
2555     std::vector<VkPhysicalDeviceGroupProperties> group_props_after_remove_group{};
2556     group_props_after_remove_group.resize(before_group_count,
2557                                           VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
2558     returned_group_count = before_group_count;
2559     ASSERT_EQ(VK_SUCCESS,
2560               inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props_after_remove_group.data()));
2561     ASSERT_EQ(before_group_count, returned_group_count);
2562     for (uint32_t group = 0; group < before_group_count; ++group) {
2563         ASSERT_EQ(group_props_after_remove_group[group].physicalDeviceCount, after_remove_group_expected_counts[group]);
2564     }
2565 
2566     // Add two devices to last group
2567     driver.physical_device_groups.back()
2568         .use_physical_device(driver.physical_devices[7])
2569         .use_physical_device(driver.physical_devices[8]);
2570 
2571     // Should be: 3 Groups { { 2, 3 }, { 6 }, { 4, 5, 7, 8 } }
2572     std::vector<VkPhysicalDeviceGroupProperties> group_props_after_add_device{};
2573     group_props_after_add_device.resize(before_group_count,
2574                                         VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
2575     returned_group_count = before_group_count;
2576     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props_after_add_device.data()));
2577     ASSERT_EQ(before_group_count, returned_group_count);
2578     for (uint32_t group = 0; group < before_group_count; ++group) {
2579         ASSERT_EQ(group_props_after_add_device[group].physicalDeviceCount, after_add_dev_expected_counts[group]);
2580     }
2581     for (auto& group : group_props_after_add_device) {
2582         VkDeviceGroupDeviceCreateInfo group_info{};
2583         group_info.sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO;
2584         group_info.physicalDeviceCount = group.physicalDeviceCount;
2585         group_info.pPhysicalDevices = &group.physicalDevices[0];
2586         DeviceWrapper dev{inst};
2587         dev.create_info.dev.pNext = &group_info;
2588         dev.CheckCreate(group.physicalDevices[0]);
2589     }
2590 }
2591 
2592 // 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)2593 void FillInRandomDeviceProps(VkPhysicalDeviceProperties& props, VkPhysicalDeviceType dev_type, uint32_t api_vers, uint32_t vendor,
2594                              uint32_t device) {
2595     props.apiVersion = api_vers;
2596     props.vendorID = vendor;
2597     props.deviceID = device;
2598     props.deviceType = dev_type;
2599     for (uint8_t idx = 0; idx < VK_UUID_SIZE; ++idx) {
2600         props.pipelineCacheUUID[idx] = static_cast<uint8_t>(rand() % 255);
2601     }
2602 }
2603 
2604 // Pass in a PNext that the fake ICD will fill in some data for.
TEST(EnumeratePhysicalDeviceGroups,FakePNext)2605 TEST(EnumeratePhysicalDeviceGroups, FakePNext) {
2606     FrameworkEnvironment env{};
2607 
2608     // ICD 0: Vulkan 1.1
2609     //   PhysDev 0: pd0, Discrete, Vulkan 1.1, Bus 7
2610     //   PhysDev 1: pd1, Integrated, Vulkan 1.1, Bus 3
2611     //   PhysDev 2: pd2, Discrete, Vulkan 1.1, Bus 6
2612     //   Group 0: PhysDev 0, PhysDev 2
2613     //   Group 1: PhysDev 1
2614     // ICD 1: Vulkan 1.1
2615     //   PhysDev 4: pd4, Discrete, Vulkan 1.1, Bus 1
2616     //   PhysDev 5: pd5, Discrete, Vulkan 1.1, Bus 4
2617     //   PhysDev 6: pd6, Discrete, Vulkan 1.1, Bus 2
2618     //   Group 0: PhysDev 5, PhysDev 6
2619     //   Group 1: PhysDev 4
2620     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, VK_API_VERSION_1_1));
2621     auto& cur_icd_0 = env.get_test_icd(0);
2622     cur_icd_0.set_icd_api_version(VK_API_VERSION_1_1);
2623     cur_icd_0.physical_devices.push_back({"pd0"});
2624     cur_icd_0.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2625     FillInRandomDeviceProps(cur_icd_0.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_API_VERSION_1_1,
2626                             888, 0xAAA001);
2627     cur_icd_0.physical_devices.push_back({"pd1"});
2628     cur_icd_0.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2629     FillInRandomDeviceProps(cur_icd_0.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
2630                             VK_API_VERSION_1_1, 888, 0xAAA002);
2631     cur_icd_0.physical_devices.push_back({"pd2"});
2632     cur_icd_0.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2633     FillInRandomDeviceProps(cur_icd_0.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_API_VERSION_1_1,
2634                             888, 0xAAA003);
2635     cur_icd_0.physical_device_groups.push_back({});
2636     cur_icd_0.physical_device_groups.back()
2637         .use_physical_device(cur_icd_0.physical_devices[0])
2638         .use_physical_device(cur_icd_0.physical_devices[2]);
2639     cur_icd_0.physical_device_groups.push_back({cur_icd_0.physical_devices[1]});
2640 
2641     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, VK_API_VERSION_1_1));
2642     auto& cur_icd_1 = env.get_test_icd(1);
2643     cur_icd_1.set_icd_api_version(VK_API_VERSION_1_1);
2644     cur_icd_1.physical_devices.push_back({"pd4"});
2645     cur_icd_1.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2646     FillInRandomDeviceProps(cur_icd_1.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_API_VERSION_1_1,
2647                             75, 0xCCCC001);
2648     cur_icd_1.physical_devices.push_back({"pd5"});
2649     cur_icd_1.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2650     FillInRandomDeviceProps(cur_icd_1.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_API_VERSION_1_1,
2651                             75, 0xCCCC002);
2652     cur_icd_1.physical_devices.push_back({"pd6"});
2653     cur_icd_1.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2654     FillInRandomDeviceProps(cur_icd_1.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_API_VERSION_1_1,
2655                             75, 0xCCCC003);
2656     cur_icd_1.physical_device_groups.push_back({});
2657     cur_icd_1.physical_device_groups.back()
2658         .use_physical_device(cur_icd_1.physical_devices[1])
2659         .use_physical_device(cur_icd_1.physical_devices[2]);
2660     cur_icd_1.physical_device_groups.push_back({cur_icd_1.physical_devices[0]});
2661 
2662     InstWrapper inst(env.vulkan_functions);
2663     inst.create_info.set_api_version(VK_API_VERSION_1_1);
2664     inst.CheckCreate();
2665 
2666     PFN_vkGetPhysicalDeviceProperties2 GetPhysDevProps2 = inst.load("vkGetPhysicalDeviceProperties2");
2667     ASSERT_NE(GetPhysDevProps2, nullptr);
2668 
2669     // NOTE: This is a fake struct to make sure the pNext chain is properly passed down to the ICD
2670     //       vkEnumeratePhysicalDeviceGroups.
2671     //       The two versions must match:
2672     //           "FakePNext" test in loader_regression_tests.cpp
2673     //           "test_vkEnumeratePhysicalDeviceGroups" in test_icd.cpp
2674     struct FakePnextSharedWithICD {
2675         VkStructureType sType;
2676         void* pNext;
2677         uint32_t value;
2678     };
2679 
2680     const uint32_t max_phys_dev_groups = 4;
2681     uint32_t group_count = max_phys_dev_groups;
2682     std::array<FakePnextSharedWithICD, max_phys_dev_groups> fake_structs;
2683     std::array<VkPhysicalDeviceGroupProperties, max_phys_dev_groups> physical_device_groups{};
2684     for (uint32_t group = 0; group < max_phys_dev_groups; ++group) {
2685         physical_device_groups[group].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES;
2686         fake_structs[group].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_PROPERTIES_EXT;
2687         physical_device_groups[group].pNext = &fake_structs[group];
2688     }
2689     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &group_count, physical_device_groups.data()));
2690     ASSERT_EQ(group_count, max_phys_dev_groups);
2691 
2692     // Value should get written to 0xDECAFBADD by the fake ICD
2693     for (uint32_t group = 0; group < max_phys_dev_groups; ++group) {
2694         ASSERT_EQ(fake_structs[group].value, 0xDECAFBAD);
2695     }
2696 }
2697 
TEST(ExtensionManual,ToolingProperties)2698 TEST(ExtensionManual, ToolingProperties) {
2699     VkPhysicalDeviceToolPropertiesEXT icd_tool_props{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TOOL_PROPERTIES_EXT,
2700                                                      nullptr,
2701                                                      "FakeICDTool",
2702                                                      "version_0_0_0_1.b",
2703                                                      VK_TOOL_PURPOSE_VALIDATION_BIT_EXT,
2704                                                      "This tool does not exist",
2705                                                      "No-Layer"};
2706     {  // No support in driver
2707         FrameworkEnvironment env{};
2708         env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device({});
2709 
2710         InstWrapper inst{env.vulkan_functions};
2711         inst.CheckCreate();
2712 
2713         auto phys_dev = inst.GetPhysDev();
2714 
2715         PFN_vkGetPhysicalDeviceToolPropertiesEXT getToolProperties = inst.load("vkGetPhysicalDeviceToolPropertiesEXT");
2716         handle_assert_has_value(getToolProperties);
2717 
2718         uint32_t tool_count = 0;
2719         ASSERT_EQ(VK_SUCCESS, getToolProperties(phys_dev, &tool_count, nullptr));
2720         ASSERT_EQ(tool_count, 0U);
2721     }
2722     {  // extension is supported in driver
2723         FrameworkEnvironment env{};
2724         env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA))
2725             .set_supports_tooling_info_ext(true)
2726             .add_tooling_property(icd_tool_props)
2727             .add_physical_device(PhysicalDevice{}.add_extension(VK_EXT_TOOLING_INFO_EXTENSION_NAME).finish());
2728 
2729         InstWrapper inst{env.vulkan_functions};
2730         inst.CheckCreate();
2731 
2732         auto phys_dev = inst.GetPhysDev();
2733 
2734         PFN_vkGetPhysicalDeviceToolPropertiesEXT getToolProperties = inst.load("vkGetPhysicalDeviceToolPropertiesEXT");
2735         handle_assert_has_value(getToolProperties);
2736         uint32_t tool_count = 0;
2737         ASSERT_EQ(VK_SUCCESS, getToolProperties(phys_dev, &tool_count, nullptr));
2738         ASSERT_EQ(tool_count, 1U);
2739         VkPhysicalDeviceToolPropertiesEXT props{};
2740         ASSERT_EQ(VK_SUCCESS, getToolProperties(phys_dev, &tool_count, &props));
2741         ASSERT_EQ(tool_count, 1U);
2742         string_eq(props.name, icd_tool_props.name);
2743     }
2744     {  // core
2745         FrameworkEnvironment env{};
2746         env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, VK_API_VERSION_1_3))
2747             .add_physical_device({})
2748             .set_supports_tooling_info_core(true)
2749             .add_tooling_property(icd_tool_props)
2750             .physical_devices.back()
2751             .properties.apiVersion = VK_MAKE_API_VERSION(0, 1, 3, 0);
2752 
2753         InstWrapper inst{env.vulkan_functions};
2754         inst.CheckCreate();
2755 
2756         auto phys_dev = inst.GetPhysDev();
2757 
2758         PFN_vkGetPhysicalDeviceToolProperties getToolProperties = inst.load("vkGetPhysicalDeviceToolProperties");
2759         handle_assert_has_value(getToolProperties);
2760         uint32_t tool_count = 0;
2761         ASSERT_EQ(VK_SUCCESS, getToolProperties(phys_dev, &tool_count, nullptr));
2762         ASSERT_EQ(tool_count, 1U);
2763         VkPhysicalDeviceToolProperties props{};
2764         ASSERT_EQ(VK_SUCCESS, getToolProperties(phys_dev, &tool_count, &props));
2765         ASSERT_EQ(tool_count, 1U);
2766         string_eq(props.name, icd_tool_props.name);
2767     }
2768 }
TEST(CreateInstance,InstanceNullLayerPtr)2769 TEST(CreateInstance, InstanceNullLayerPtr) {
2770     FrameworkEnvironment env{};
2771     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
2772     VkInstance inst = VK_NULL_HANDLE;
2773     VkInstanceCreateInfo info{};
2774     info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
2775     info.enabledLayerCount = 1;
2776 
2777     ASSERT_EQ(env.vulkan_functions.vkCreateInstance(&info, VK_NULL_HANDLE, &inst), VK_ERROR_LAYER_NOT_PRESENT);
2778 }
TEST(CreateInstance,InstanceNullExtensionPtr)2779 TEST(CreateInstance, InstanceNullExtensionPtr) {
2780     FrameworkEnvironment env{};
2781     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
2782     VkInstance inst = VK_NULL_HANDLE;
2783     VkInstanceCreateInfo info{};
2784     info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
2785     info.enabledExtensionCount = 1;
2786 
2787     ASSERT_EQ(env.vulkan_functions.vkCreateInstance(&info, VK_NULL_HANDLE, &inst), VK_ERROR_EXTENSION_NOT_PRESENT);
2788 }
2789 
2790 #if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__GNU__) || defined(__QNX__)
2791 // NOTE: Sort order only affects Linux
TEST(SortedPhysicalDevices,DevicesSortEnabled10NoAppExt)2792 TEST(SortedPhysicalDevices, DevicesSortEnabled10NoAppExt) {
2793     FrameworkEnvironment env{};
2794     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
2795     env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
2796     env.get_test_icd(0).physical_devices.push_back({"pd0"});
2797     env.get_test_icd(0).physical_devices.back().set_pci_bus(7);
2798     FillInRandomDeviceProps(env.get_test_icd(0).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU,
2799                             VK_API_VERSION_1_1, 888, 0xAAA001);
2800     env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2801     env.get_test_icd(0).physical_devices.push_back({"pd1"});
2802     env.get_test_icd(0).physical_devices.back().set_pci_bus(3);
2803     FillInRandomDeviceProps(env.get_test_icd(0).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
2804                             VK_API_VERSION_1_1, 888, 0xAAA002);
2805     env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2806 
2807     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_0));
2808     env.get_test_icd(1).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
2809     env.get_test_icd(1).physical_devices.push_back({"pd2"});
2810     env.get_test_icd(1).physical_devices.back().set_pci_bus(0);
2811     FillInRandomDeviceProps(env.get_test_icd(1).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_CPU, VK_API_VERSION_1_0,
2812                             1, 0xBBBB001);
2813     env.get_test_icd(1).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2814 
2815     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
2816     env.get_test_icd(2).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
2817     env.get_test_icd(2).physical_devices.push_back({"pd3"});
2818     env.get_test_icd(2).physical_devices.back().set_pci_bus(1);
2819     FillInRandomDeviceProps(env.get_test_icd(2).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU,
2820                             VK_API_VERSION_1_1, 75, 0xCCCC001);
2821     env.get_test_icd(2).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2822     env.get_test_icd(2).physical_devices.push_back({"pd4"});
2823     env.get_test_icd(2).physical_devices.back().set_pci_bus(4);
2824     FillInRandomDeviceProps(env.get_test_icd(2).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU,
2825                             VK_API_VERSION_1_0, 75, 0xCCCC002);
2826     env.get_test_icd(2).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2827 
2828     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
2829     env.get_test_icd(3).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
2830     env.get_test_icd(3).physical_devices.push_back({"pd5"});
2831     env.get_test_icd(3).physical_devices.back().set_pci_bus(0);
2832     FillInRandomDeviceProps(env.get_test_icd(3).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU,
2833                             VK_API_VERSION_1_1, 6940, 0xDDDD001);
2834     env.get_test_icd(3).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2835 
2836     InstWrapper instance(env.vulkan_functions);
2837     instance.CheckCreate();
2838 
2839     const uint32_t max_phys_devs = 6;
2840     uint32_t device_count = max_phys_devs;
2841     std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
2842     ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
2843     ASSERT_EQ(device_count, max_phys_devs);
2844 
2845     for (uint32_t dev = 0; dev < device_count; ++dev) {
2846         VkPhysicalDeviceProperties props{};
2847         instance->vkGetPhysicalDeviceProperties(physical_devices[dev], &props);
2848 
2849         switch (dev) {
2850             case 0:
2851                 ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
2852                 ASSERT_EQ(true, !strcmp("pd3", props.deviceName));
2853                 ASSERT_EQ(props.vendorID, 75);
2854                 ASSERT_EQ(props.deviceID, 0xCCCC001);
2855                 break;
2856             case 1:
2857                 ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
2858                 ASSERT_EQ(true, !strcmp("pd4", props.deviceName));
2859                 ASSERT_EQ(props.vendorID, 75);
2860                 ASSERT_EQ(props.deviceID, 0xCCCC002);
2861                 break;
2862             case 2:
2863                 ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
2864                 ASSERT_EQ(true, !strcmp("pd0", props.deviceName));
2865                 ASSERT_EQ(props.vendorID, 888);
2866                 ASSERT_EQ(props.deviceID, 0xAAA001);
2867                 break;
2868             case 3:
2869                 ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU);
2870                 ASSERT_EQ(true, !strcmp("pd1", props.deviceName));
2871                 ASSERT_EQ(props.vendorID, 888);
2872                 ASSERT_EQ(props.deviceID, 0xAAA002);
2873                 break;
2874             case 4:
2875                 ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU);
2876                 ASSERT_EQ(true, !strcmp("pd5", props.deviceName));
2877                 ASSERT_EQ(props.vendorID, 6940U);
2878                 ASSERT_EQ(props.deviceID, 0xDDDD001);
2879                 break;
2880             case 5:
2881                 ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_CPU);
2882                 ASSERT_EQ(true, !strcmp("pd2", props.deviceName));
2883                 ASSERT_EQ(props.vendorID, 1U);
2884                 ASSERT_EQ(props.deviceID, 0xBBBB001);
2885                 break;
2886             default:
2887                 ASSERT_EQ(false, true);
2888         }
2889     }
2890 
2891     // Make sure if we call enumerate again, the information is the same
2892     std::array<VkPhysicalDevice, max_phys_devs> physical_devices_again;
2893     ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices_again.data()));
2894     ASSERT_EQ(device_count, max_phys_devs);
2895     for (uint32_t dev = 0; dev < device_count; ++dev) {
2896         ASSERT_EQ(physical_devices[dev], physical_devices_again[dev]);
2897     }
2898 }
2899 
TEST(SortedPhysicalDevices,DevicesSortEnabled10AppExt)2900 TEST(SortedPhysicalDevices, DevicesSortEnabled10AppExt) {
2901     FrameworkEnvironment env{};
2902     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
2903     env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
2904     env.get_test_icd(0).physical_devices.push_back({"pd0"});
2905     env.get_test_icd(0).physical_devices.back().set_pci_bus(7);
2906     FillInRandomDeviceProps(env.get_test_icd(0).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU,
2907                             VK_API_VERSION_1_1, 888, 0xAAA001);
2908     env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2909     env.get_test_icd(0).physical_devices.push_back({"pd1"});
2910     env.get_test_icd(0).physical_devices.back().set_pci_bus(3);
2911     FillInRandomDeviceProps(env.get_test_icd(0).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
2912                             VK_API_VERSION_1_1, 888, 0xAAA002);
2913     env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2914 
2915     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_0));
2916     env.get_test_icd(1).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
2917     env.get_test_icd(1).physical_devices.push_back({"pd2"});
2918     env.get_test_icd(1).physical_devices.back().set_pci_bus(0);
2919     FillInRandomDeviceProps(env.get_test_icd(1).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_CPU, VK_API_VERSION_1_0,
2920                             1, 0xBBBB001);
2921     env.get_test_icd(1).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2922 
2923     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
2924     env.get_test_icd(2).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
2925     env.get_test_icd(2).physical_devices.push_back({"pd3"});
2926     env.get_test_icd(2).physical_devices.back().set_pci_bus(1);
2927     FillInRandomDeviceProps(env.get_test_icd(2).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU,
2928                             VK_API_VERSION_1_1, 75, 0xCCCC001);
2929     env.get_test_icd(2).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2930     env.get_test_icd(2).physical_devices.push_back({"pd4"});
2931     env.get_test_icd(2).physical_devices.back().set_pci_bus(4);
2932     FillInRandomDeviceProps(env.get_test_icd(2).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU,
2933                             VK_API_VERSION_1_0, 75, 0xCCCC002);
2934     env.get_test_icd(2).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2935 
2936     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
2937     env.get_test_icd(3).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
2938     env.get_test_icd(3).physical_devices.push_back({"pd5"});
2939     env.get_test_icd(3).physical_devices.back().set_pci_bus(0);
2940     FillInRandomDeviceProps(env.get_test_icd(3).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU,
2941                             VK_API_VERSION_1_1, 6940, 0xDDDD001);
2942     env.get_test_icd(3).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
2943 
2944     InstWrapper instance(env.vulkan_functions);
2945     instance.create_info.add_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
2946     instance.CheckCreate();
2947 
2948     PFN_vkGetPhysicalDeviceProperties2KHR GetPhysDevProps2 = instance.load("vkGetPhysicalDeviceProperties2KHR");
2949     ASSERT_NE(GetPhysDevProps2, nullptr);
2950 
2951     const uint32_t max_phys_devs = 6;
2952     uint32_t device_count = max_phys_devs;
2953     std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
2954     ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
2955     ASSERT_EQ(device_count, max_phys_devs);
2956 
2957     for (uint32_t dev = 0; dev < device_count; ++dev) {
2958         VkPhysicalDeviceProperties props{};
2959         instance->vkGetPhysicalDeviceProperties(physical_devices[dev], &props);
2960         VkPhysicalDeviceProperties2KHR props2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2};
2961         VkPhysicalDevicePCIBusInfoPropertiesEXT pci_bus_info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT};
2962         props2.pNext = &pci_bus_info;
2963         GetPhysDevProps2(physical_devices[dev], &props2);
2964 
2965         switch (dev) {
2966             case 0:
2967                 ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
2968                 ASSERT_EQ(true, !strcmp("pd3", props.deviceName));
2969                 ASSERT_EQ(props.vendorID, 75);
2970                 ASSERT_EQ(props.deviceID, 0xCCCC001);
2971                 ASSERT_EQ(pci_bus_info.pciBus, 1U);
2972                 break;
2973             case 1:
2974                 ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
2975                 ASSERT_EQ(true, !strcmp("pd4", props.deviceName));
2976                 ASSERT_EQ(props.vendorID, 75);
2977                 ASSERT_EQ(props.deviceID, 0xCCCC002);
2978                 ASSERT_EQ(pci_bus_info.pciBus, 4U);
2979                 break;
2980             case 2:
2981                 ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
2982                 ASSERT_EQ(true, !strcmp("pd0", props.deviceName));
2983                 ASSERT_EQ(props.vendorID, 888);
2984                 ASSERT_EQ(props.deviceID, 0xAAA001);
2985                 ASSERT_EQ(pci_bus_info.pciBus, 7);
2986                 break;
2987             case 3:
2988                 ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU);
2989                 ASSERT_EQ(true, !strcmp("pd1", props.deviceName));
2990                 ASSERT_EQ(props.vendorID, 888);
2991                 ASSERT_EQ(props.deviceID, 0xAAA002);
2992                 ASSERT_EQ(pci_bus_info.pciBus, 3U);
2993                 break;
2994             case 4:
2995                 ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU);
2996                 ASSERT_EQ(true, !strcmp("pd5", props.deviceName));
2997                 ASSERT_EQ(props.vendorID, 6940U);
2998                 ASSERT_EQ(props.deviceID, 0xDDDD001);
2999                 ASSERT_EQ(pci_bus_info.pciBus, 0U);
3000                 break;
3001             case 5:
3002                 ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_CPU);
3003                 ASSERT_EQ(true, !strcmp("pd2", props.deviceName));
3004                 ASSERT_EQ(props.vendorID, 1U);
3005                 ASSERT_EQ(props.deviceID, 0xBBBB001);
3006                 ASSERT_EQ(pci_bus_info.pciBus, 0U);
3007                 break;
3008             default:
3009                 ASSERT_EQ(false, true);
3010         }
3011     }
3012 
3013     // Make sure if we call enumerate again, the information is the same
3014     std::array<VkPhysicalDevice, max_phys_devs> physical_devices_again;
3015     ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices_again.data()));
3016     ASSERT_EQ(device_count, max_phys_devs);
3017     for (uint32_t dev = 0; dev < device_count; ++dev) {
3018         ASSERT_EQ(physical_devices[dev], physical_devices_again[dev]);
3019     }
3020 }
3021 
TEST(SortedPhysicalDevices,DevicesSortEnabled11)3022 TEST(SortedPhysicalDevices, DevicesSortEnabled11) {
3023     FrameworkEnvironment env{};
3024     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
3025     env.get_test_icd(0).set_icd_api_version(VK_API_VERSION_1_1);
3026     env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
3027     env.get_test_icd(0).physical_devices.push_back({"pd0"});
3028     env.get_test_icd(0).physical_devices.back().set_pci_bus(7);
3029     FillInRandomDeviceProps(env.get_test_icd(0).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU,
3030                             VK_API_VERSION_1_0, 888, 0xAAA001);
3031     env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3032     env.get_test_icd(0).physical_devices.push_back({"pd1"});
3033     env.get_test_icd(0).physical_devices.back().set_pci_bus(3);
3034     FillInRandomDeviceProps(env.get_test_icd(0).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
3035                             VK_API_VERSION_1_0, 888, 0xAAA002);
3036     env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3037 
3038     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
3039     env.get_test_icd(1).set_icd_api_version(VK_API_VERSION_1_1);
3040     env.get_test_icd(1).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
3041     env.get_test_icd(1).physical_devices.push_back({"pd2"});
3042     env.get_test_icd(1).physical_devices.back().set_pci_bus(0);
3043     FillInRandomDeviceProps(env.get_test_icd(1).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_CPU, VK_API_VERSION_1_0,
3044                             1, 0xBBBB001);
3045     env.get_test_icd(1).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3046 
3047     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
3048     env.get_test_icd(2).set_icd_api_version(VK_API_VERSION_1_1);
3049     env.get_test_icd(2).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
3050     env.get_test_icd(2).physical_devices.push_back({"pd3"});
3051     env.get_test_icd(2).physical_devices.back().set_pci_bus(1);
3052     FillInRandomDeviceProps(env.get_test_icd(2).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU,
3053                             VK_API_VERSION_1_1, 75, 0xCCCC001);
3054     env.get_test_icd(2).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3055     env.get_test_icd(2).physical_devices.push_back({"pd4"});
3056     env.get_test_icd(2).physical_devices.back().set_pci_bus(4);
3057     FillInRandomDeviceProps(env.get_test_icd(2).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU,
3058                             VK_API_VERSION_1_1, 75, 0xCCCC002);
3059     env.get_test_icd(2).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3060 
3061     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
3062     env.get_test_icd(3).set_icd_api_version(VK_API_VERSION_1_1);
3063     env.get_test_icd(3).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
3064     env.get_test_icd(3).physical_devices.push_back({"pd5"});
3065     env.get_test_icd(3).physical_devices.back().set_pci_bus(0);
3066     FillInRandomDeviceProps(env.get_test_icd(3).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU,
3067                             VK_API_VERSION_1_1, 6940, 0xDDDD001);
3068     env.get_test_icd(3).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3069 
3070     InstWrapper instance(env.vulkan_functions);
3071     instance.create_info.set_api_version(VK_API_VERSION_1_1);
3072     instance.CheckCreate();
3073 
3074     PFN_vkGetPhysicalDeviceProperties2 GetPhysDevProps2 = instance.load("vkGetPhysicalDeviceProperties2");
3075     ASSERT_NE(GetPhysDevProps2, nullptr);
3076 
3077     const uint32_t max_phys_devs = 6;
3078     uint32_t device_count = max_phys_devs;
3079     std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
3080     ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
3081     ASSERT_EQ(device_count, max_phys_devs);
3082 
3083     for (uint32_t dev = 0; dev < device_count; ++dev) {
3084         VkPhysicalDeviceProperties props{};
3085         instance->vkGetPhysicalDeviceProperties(physical_devices[dev], &props);
3086         VkPhysicalDeviceProperties2KHR props2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2};
3087         VkPhysicalDevicePCIBusInfoPropertiesEXT pci_bus_info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT};
3088         props2.pNext = &pci_bus_info;
3089         GetPhysDevProps2(physical_devices[dev], &props2);
3090 
3091         switch (dev) {
3092             case 0:
3093                 ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
3094                 ASSERT_EQ(true, !strcmp("pd3", props.deviceName));
3095                 ASSERT_EQ(props.vendorID, 75);
3096                 ASSERT_EQ(props.deviceID, 0xCCCC001);
3097                 ASSERT_EQ(pci_bus_info.pciBus, 1U);
3098                 break;
3099             case 1:
3100                 ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
3101                 ASSERT_EQ(true, !strcmp("pd4", props.deviceName));
3102                 ASSERT_EQ(props.vendorID, 75);
3103                 ASSERT_EQ(props.deviceID, 0xCCCC002);
3104                 ASSERT_EQ(pci_bus_info.pciBus, 4U);
3105                 break;
3106             case 2:
3107                 ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
3108                 ASSERT_EQ(true, !strcmp("pd0", props.deviceName));
3109                 ASSERT_EQ(props.vendorID, 888);
3110                 ASSERT_EQ(props.deviceID, 0xAAA001);
3111                 ASSERT_EQ(pci_bus_info.pciBus, 7);
3112                 break;
3113             case 3:
3114                 ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU);
3115                 ASSERT_EQ(true, !strcmp("pd1", props.deviceName));
3116                 ASSERT_EQ(props.vendorID, 888);
3117                 ASSERT_EQ(props.deviceID, 0xAAA002);
3118                 ASSERT_EQ(pci_bus_info.pciBus, 3U);
3119                 break;
3120             case 4:
3121                 ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU);
3122                 ASSERT_EQ(true, !strcmp("pd5", props.deviceName));
3123                 ASSERT_EQ(props.vendorID, 6940U);
3124                 ASSERT_EQ(props.deviceID, 0xDDDD001);
3125                 ASSERT_EQ(pci_bus_info.pciBus, 0U);
3126                 break;
3127             case 5:
3128                 ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_CPU);
3129                 ASSERT_EQ(true, !strcmp("pd2", props.deviceName));
3130                 ASSERT_EQ(props.vendorID, 1U);
3131                 ASSERT_EQ(props.deviceID, 0xBBBB001);
3132                 ASSERT_EQ(pci_bus_info.pciBus, 0U);
3133                 break;
3134             default:
3135                 ASSERT_EQ(false, true);
3136         }
3137     }
3138 
3139     // Make sure if we call enumerate again, the information is the same
3140     std::array<VkPhysicalDevice, max_phys_devs> physical_devices_again;
3141     ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices_again.data()));
3142     ASSERT_EQ(device_count, max_phys_devs);
3143     for (uint32_t dev = 0; dev < device_count; ++dev) {
3144         ASSERT_EQ(physical_devices[dev], physical_devices_again[dev]);
3145     }
3146 }
3147 
TEST(SortedPhysicalDevices,DevicesSortedDisabled)3148 TEST(SortedPhysicalDevices, DevicesSortedDisabled) {
3149     FrameworkEnvironment env{};
3150 
3151     EnvVarWrapper disable_select_env_var{"VK_LOADER_DISABLE_SELECT", "1"};
3152 
3153     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_0));
3154     env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
3155     env.get_test_icd(0).physical_devices.push_back({"pd0"});
3156     FillInRandomDeviceProps(env.get_test_icd(0).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU,
3157                             VK_API_VERSION_1_0, 888, 0xAAA001);
3158     env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3159     env.get_test_icd(0).physical_devices.push_back({"pd1"});
3160     FillInRandomDeviceProps(env.get_test_icd(0).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
3161                             VK_API_VERSION_1_0, 888, 0xAAA002);
3162     env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3163 
3164     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_0));
3165     env.get_test_icd(1).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
3166     env.get_test_icd(1).physical_devices.push_back({"pd2"});
3167     FillInRandomDeviceProps(env.get_test_icd(1).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_CPU, VK_API_VERSION_1_0,
3168                             1, 0xBBBB001);
3169     env.get_test_icd(1).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3170 
3171     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_0));
3172     env.get_test_icd(2).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
3173     env.get_test_icd(2).physical_devices.push_back({"pd3"});
3174     FillInRandomDeviceProps(env.get_test_icd(2).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU,
3175                             VK_API_VERSION_1_0, 75, 0xCCCC001);
3176     env.get_test_icd(2).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3177     env.get_test_icd(2).physical_devices.push_back({"pd4"});
3178     FillInRandomDeviceProps(env.get_test_icd(2).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU,
3179                             VK_API_VERSION_1_0, 75, 0xCCCC002);
3180     env.get_test_icd(2).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3181 
3182     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_0));
3183     env.get_test_icd(3).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
3184     env.get_test_icd(3).physical_devices.push_back({"pd5"});
3185     FillInRandomDeviceProps(env.get_test_icd(3).physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU,
3186                             VK_API_VERSION_1_0, 6940, 0xDDDD001);
3187     env.get_test_icd(3).physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3188 
3189     InstWrapper instance(env.vulkan_functions);
3190     instance.create_info.add_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
3191     instance.CheckCreate();
3192 
3193     // Just make sure we have the correct number of devices
3194     const uint32_t max_phys_devs = 6;
3195     uint32_t device_count = max_phys_devs;
3196     std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
3197     ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
3198     ASSERT_EQ(device_count, max_phys_devs);
3199 
3200     // make sure the order is what we started with - but its a bit wonky due to the loader reading physical devices "backwards"
3201     VkPhysicalDeviceProperties props{};
3202     instance->vkGetPhysicalDeviceProperties(physical_devices[0], &props);
3203     ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU);
3204     ASSERT_STREQ(props.deviceName, "pd5");
3205 
3206     instance->vkGetPhysicalDeviceProperties(physical_devices[1], &props);
3207     ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
3208     ASSERT_STREQ(props.deviceName, "pd3");
3209 
3210     instance->vkGetPhysicalDeviceProperties(physical_devices[2], &props);
3211     ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
3212     ASSERT_STREQ(props.deviceName, "pd4");
3213 
3214     instance->vkGetPhysicalDeviceProperties(physical_devices[3], &props);
3215     ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_CPU);
3216     ASSERT_STREQ(props.deviceName, "pd2");
3217 
3218     instance->vkGetPhysicalDeviceProperties(physical_devices[4], &props);
3219     ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
3220     ASSERT_STREQ(props.deviceName, "pd0");
3221 
3222     instance->vkGetPhysicalDeviceProperties(physical_devices[5], &props);
3223     ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU);
3224     ASSERT_STREQ(props.deviceName, "pd1");
3225 
3226     // Make sure if we call enumerate again, the information is the same
3227     std::array<VkPhysicalDevice, max_phys_devs> physical_devices_again;
3228     ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices_again.data()));
3229     ASSERT_EQ(device_count, max_phys_devs);
3230     for (uint32_t dev = 0; dev < device_count; ++dev) {
3231         ASSERT_EQ(physical_devices[dev], physical_devices_again[dev]);
3232     }
3233 }
3234 
TEST(SortedPhysicalDevices,DeviceGroupsSortedEnabled)3235 TEST(SortedPhysicalDevices, DeviceGroupsSortedEnabled) {
3236     FrameworkEnvironment env{};
3237 
3238     // ICD 0: Vulkan 1.1
3239     //   PhysDev 0: pd0, Discrete, Vulkan 1.1, Bus 7
3240     //   PhysDev 1: pd1, Integrated, Vulkan 1.1, Bus 3
3241     //   PhysDev 2: pd2, Discrete, Vulkan 1.1, Bus 6
3242     //   Group 0: PhysDev 0, PhysDev 2
3243     //   Group 1: PhysDev 1
3244     // ICD 1: Vulkan 1.1
3245     //   PhysDev 3: pd3, CPU, Vulkan 1.1, Bus 0
3246     // ICD 2: Vulkan 1.1
3247     //   PhysDev 4: pd4, Discrete, Vulkan 1.1, Bus 1
3248     //   PhysDev 5: pd5, Discrete, Vulkan 1.1, Bus 4
3249     //   PhysDev 6: pd6, Discrete, Vulkan 1.1, Bus 2
3250     //   Group 0: PhysDev 5, PhysDev 6
3251     //   Group 1: PhysDev 4
3252     // ICD 3: Vulkan 1.1
3253     //   PhysDev 7: pd7, Virtual, Vulkan 1.1, Bus 0
3254     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
3255     auto& cur_icd_0 = env.get_test_icd(0);
3256     cur_icd_0.set_icd_api_version(VK_API_VERSION_1_1);
3257     cur_icd_0.physical_devices.push_back({"pd0"});
3258     cur_icd_0.physical_devices.back().set_pci_bus(7);
3259     cur_icd_0.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3260     FillInRandomDeviceProps(cur_icd_0.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_API_VERSION_1_1,
3261                             888, 0xAAA001);
3262     cur_icd_0.physical_devices.push_back({"pd1"});
3263     cur_icd_0.physical_devices.back().set_pci_bus(3);
3264     cur_icd_0.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3265     FillInRandomDeviceProps(cur_icd_0.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
3266                             VK_API_VERSION_1_1, 888, 0xAAA002);
3267     cur_icd_0.physical_devices.push_back({"pd2"});
3268     cur_icd_0.physical_devices.back().set_pci_bus(6);
3269     cur_icd_0.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3270     FillInRandomDeviceProps(cur_icd_0.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_API_VERSION_1_1,
3271                             888, 0xAAA003);
3272     cur_icd_0.physical_device_groups.push_back({});
3273     cur_icd_0.physical_device_groups.back()
3274         .use_physical_device(cur_icd_0.physical_devices[0])
3275         .use_physical_device(cur_icd_0.physical_devices[2]);
3276     cur_icd_0.physical_device_groups.push_back({cur_icd_0.physical_devices[1]});
3277 
3278     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
3279     auto& cur_icd_1 = env.get_test_icd(1);
3280     cur_icd_1.set_icd_api_version(VK_API_VERSION_1_1);
3281     cur_icd_1.physical_devices.push_back({"pd3"});
3282     cur_icd_1.physical_devices.back().set_pci_bus(0);
3283     cur_icd_1.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3284     FillInRandomDeviceProps(cur_icd_1.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_CPU, VK_API_VERSION_1_1, 1,
3285                             0xBBBB001);
3286 
3287     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
3288     auto& cur_icd_2 = env.get_test_icd(2);
3289     cur_icd_2.set_icd_api_version(VK_API_VERSION_1_1);
3290     cur_icd_2.physical_devices.push_back({"pd4"});
3291     cur_icd_2.physical_devices.back().set_pci_bus(1);
3292     cur_icd_2.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3293     FillInRandomDeviceProps(cur_icd_2.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_API_VERSION_1_1,
3294                             75, 0xCCCC001);
3295     cur_icd_2.physical_devices.push_back({"pd5"});
3296     cur_icd_2.physical_devices.back().set_pci_bus(4);
3297     cur_icd_2.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3298     FillInRandomDeviceProps(cur_icd_2.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_API_VERSION_1_1,
3299                             75, 0xCCCC002);
3300     cur_icd_2.physical_devices.push_back({"pd6"});
3301     cur_icd_2.physical_devices.back().set_pci_bus(2);
3302     cur_icd_2.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3303     FillInRandomDeviceProps(cur_icd_2.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_API_VERSION_1_1,
3304                             75, 0xCCCC003);
3305     cur_icd_2.physical_device_groups.push_back({});
3306     cur_icd_2.physical_device_groups.back()
3307         .use_physical_device(cur_icd_2.physical_devices[1])
3308         .use_physical_device(cur_icd_2.physical_devices[2]);
3309     cur_icd_2.physical_device_groups.push_back({cur_icd_2.physical_devices[0]});
3310 
3311     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
3312     auto& cur_icd_3 = env.get_test_icd(3);
3313     cur_icd_3.set_icd_api_version(VK_API_VERSION_1_1);
3314     cur_icd_3.physical_devices.push_back({"pd7"});
3315     cur_icd_3.physical_devices.back().set_pci_bus(0);
3316     cur_icd_3.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3317     FillInRandomDeviceProps(cur_icd_3.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU, VK_API_VERSION_1_1,
3318                             6940, 0xDDDD001);
3319 
3320     InstWrapper inst(env.vulkan_functions);
3321     inst.create_info.set_api_version(VK_API_VERSION_1_1);
3322     inst.CheckCreate();
3323 
3324     PFN_vkGetPhysicalDeviceProperties2 GetPhysDevProps2 = inst.load("vkGetPhysicalDeviceProperties2");
3325     ASSERT_NE(GetPhysDevProps2, nullptr);
3326 
3327     const uint32_t max_phys_devs = 8;
3328     uint32_t device_count = max_phys_devs;
3329     std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
3330     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &device_count, physical_devices.data()));
3331     ASSERT_EQ(device_count, max_phys_devs);
3332 
3333     const uint32_t max_phys_dev_groups = 6;
3334     uint32_t group_count = max_phys_dev_groups;
3335     std::array<VkPhysicalDeviceGroupProperties, max_phys_dev_groups> physical_device_groups{};
3336     for (auto& group : physical_device_groups) group.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES;
3337     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &group_count, physical_device_groups.data()));
3338     ASSERT_EQ(group_count, max_phys_dev_groups);
3339 
3340     uint32_t cur_dev = 0;
3341     for (uint32_t group = 0; group < max_phys_dev_groups; ++group) {
3342         for (uint32_t dev = 0; dev < physical_device_groups[group].physicalDeviceCount; ++dev) {
3343             VkPhysicalDeviceProperties props{};
3344             inst->vkGetPhysicalDeviceProperties(physical_device_groups[group].physicalDevices[dev], &props);
3345             VkPhysicalDeviceProperties2 props2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2};
3346             VkPhysicalDevicePCIBusInfoPropertiesEXT pci_bus_info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT};
3347             props2.pNext = &pci_bus_info;
3348             GetPhysDevProps2(physical_device_groups[group].physicalDevices[dev], &props2);
3349             switch (cur_dev++) {
3350                 case 0:
3351                     ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
3352                     ASSERT_EQ(true, !strcmp("pd4", props.deviceName));
3353                     ASSERT_EQ(props.vendorID, 75);
3354                     ASSERT_EQ(props.deviceID, 0xCCCC001);
3355                     ASSERT_EQ(pci_bus_info.pciBus, 1U);
3356                     break;
3357                 case 1:
3358                     ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
3359                     ASSERT_EQ(true, !strcmp("pd6", props.deviceName));
3360                     ASSERT_EQ(props.vendorID, 75);
3361                     ASSERT_EQ(props.deviceID, 0xCCCC003);
3362                     ASSERT_EQ(pci_bus_info.pciBus, 2U);
3363                     break;
3364                 case 2:
3365                     ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
3366                     ASSERT_EQ(true, !strcmp("pd5", props.deviceName));
3367                     ASSERT_EQ(props.vendorID, 75);
3368                     ASSERT_EQ(props.deviceID, 0xCCCC002);
3369                     ASSERT_EQ(pci_bus_info.pciBus, 4U);
3370                     break;
3371                 case 3:
3372                     ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
3373                     ASSERT_EQ(true, !strcmp("pd2", props.deviceName));
3374                     ASSERT_EQ(props.vendorID, 888);
3375                     ASSERT_EQ(props.deviceID, 0xAAA003);
3376                     ASSERT_EQ(pci_bus_info.pciBus, 6);
3377                     break;
3378                 case 4:
3379                     ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
3380                     ASSERT_EQ(true, !strcmp("pd0", props.deviceName));
3381                     ASSERT_EQ(props.vendorID, 888);
3382                     ASSERT_EQ(props.deviceID, 0xAAA001);
3383                     ASSERT_EQ(pci_bus_info.pciBus, 7);
3384                     break;
3385                 case 5:
3386                     ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU);
3387                     ASSERT_EQ(true, !strcmp("pd1", props.deviceName));
3388                     ASSERT_EQ(props.vendorID, 888);
3389                     ASSERT_EQ(props.deviceID, 0xAAA002);
3390                     ASSERT_EQ(pci_bus_info.pciBus, 3U);
3391                     break;
3392                 case 6:
3393                     ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU);
3394                     ASSERT_EQ(true, !strcmp("pd7", props.deviceName));
3395                     ASSERT_EQ(props.vendorID, 6940U);
3396                     ASSERT_EQ(props.deviceID, 0xDDDD001);
3397                     ASSERT_EQ(pci_bus_info.pciBus, 0U);
3398                     break;
3399                 case 7:
3400                     ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_CPU);
3401                     ASSERT_EQ(true, !strcmp("pd3", props.deviceName));
3402                     ASSERT_EQ(props.vendorID, 1U);
3403                     ASSERT_EQ(props.deviceID, 0xBBBB001);
3404                     ASSERT_EQ(pci_bus_info.pciBus, 0U);
3405                     break;
3406                 default:
3407                     ASSERT_EQ(false, true);
3408             }
3409         }
3410     }
3411 
3412     // Make sure if we call enumerate again, the information is the same
3413     std::array<VkPhysicalDeviceGroupProperties, max_phys_dev_groups> physical_device_groups_again{};
3414     for (auto& group : physical_device_groups_again) group.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES;
3415 
3416     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &group_count, physical_device_groups_again.data()));
3417     ASSERT_EQ(group_count, max_phys_dev_groups);
3418     for (uint32_t group = 0; group < max_phys_dev_groups; ++group) {
3419         ASSERT_EQ(physical_device_groups[group].physicalDeviceCount, physical_device_groups_again[group].physicalDeviceCount);
3420         for (uint32_t dev = 0; dev < physical_device_groups[group].physicalDeviceCount; ++dev) {
3421             ASSERT_EQ(physical_device_groups[group].physicalDevices[dev], physical_device_groups_again[group].physicalDevices[dev]);
3422         }
3423     }
3424 }
3425 
TEST(SortedPhysicalDevices,DeviceGroupsSortedDisabled)3426 TEST(SortedPhysicalDevices, DeviceGroupsSortedDisabled) {
3427     FrameworkEnvironment env{};
3428 
3429     EnvVarWrapper disable_select_env_var{"VK_LOADER_DISABLE_SELECT", "1"};
3430 
3431     // ICD 0: Vulkan 1.1
3432     //   PhysDev 0: pd0, Discrete, Vulkan 1.1, Bus 7
3433     //   PhysDev 1: pd1, Integrated, Vulkan 1.1, Bus 3
3434     //   PhysDev 2: pd2, Discrete, Vulkan 1.1, Bus 6
3435     //   Group 0: PhysDev 0, PhysDev 2
3436     //   Group 1: PhysDev 1
3437     // ICD 1: Vulkan 1.1
3438     //   PhysDev 3: pd3, CPU, Vulkan 1.1, Bus 0
3439     // ICD 2: Vulkan 1.1
3440     //   PhysDev 4: pd4, Discrete, Vulkan 1.1, Bus 1
3441     //   PhysDev 5: pd5, Discrete, Vulkan 1.1, Bus 4
3442     //   PhysDev 6: pd6, Discrete, Vulkan 1.1, Bus 2
3443     //   Group 0: PhysDev 5, PhysDev 6
3444     //   Group 1: PhysDev 4
3445     // ICD 3: Vulkan 1.1
3446     //   PhysDev 7: pd7, Virtual, Vulkan 1.1, Bus 0
3447     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
3448     auto& cur_icd_0 = env.get_test_icd(0);
3449     cur_icd_0.set_icd_api_version(VK_API_VERSION_1_1);
3450     cur_icd_0.physical_devices.push_back({"pd0"});
3451     cur_icd_0.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3452     FillInRandomDeviceProps(cur_icd_0.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_API_VERSION_1_1,
3453                             888, 0xAAA001);
3454     cur_icd_0.physical_devices.push_back({"pd1"});
3455     cur_icd_0.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3456     FillInRandomDeviceProps(cur_icd_0.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
3457                             VK_API_VERSION_1_1, 888, 0xAAA002);
3458     cur_icd_0.physical_devices.push_back({"pd2"});
3459     cur_icd_0.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3460     FillInRandomDeviceProps(cur_icd_0.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_API_VERSION_1_1,
3461                             888, 0xAAA003);
3462     cur_icd_0.physical_device_groups.push_back({});
3463     cur_icd_0.physical_device_groups.back()
3464         .use_physical_device(cur_icd_0.physical_devices[0])
3465         .use_physical_device(cur_icd_0.physical_devices[2]);
3466     cur_icd_0.physical_device_groups.push_back({cur_icd_0.physical_devices[1]});
3467 
3468     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
3469     auto& cur_icd_1 = env.get_test_icd(1);
3470     cur_icd_1.set_icd_api_version(VK_API_VERSION_1_1);
3471     cur_icd_1.physical_devices.push_back({"pd3"});
3472     cur_icd_1.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3473     FillInRandomDeviceProps(cur_icd_1.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_CPU, VK_API_VERSION_1_1, 1,
3474                             0xBBBB001);
3475 
3476     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
3477     auto& cur_icd_2 = env.get_test_icd(2);
3478     cur_icd_2.set_icd_api_version(VK_API_VERSION_1_1);
3479     cur_icd_2.physical_devices.push_back({"pd4"});
3480     cur_icd_2.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3481     FillInRandomDeviceProps(cur_icd_2.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_API_VERSION_1_1,
3482                             75, 0xCCCC001);
3483     cur_icd_2.physical_devices.push_back({"pd5"});
3484     cur_icd_2.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3485     FillInRandomDeviceProps(cur_icd_2.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_API_VERSION_1_1,
3486                             75, 0xCCCC002);
3487     cur_icd_2.physical_devices.push_back({"pd6"});
3488     cur_icd_2.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3489     FillInRandomDeviceProps(cur_icd_2.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_API_VERSION_1_1,
3490                             75, 0xCCCC003);
3491     cur_icd_2.physical_device_groups.push_back({});
3492     cur_icd_2.physical_device_groups.back()
3493         .use_physical_device(cur_icd_2.physical_devices[1])
3494         .use_physical_device(cur_icd_2.physical_devices[2]);
3495     cur_icd_2.physical_device_groups.push_back({cur_icd_2.physical_devices[0]});
3496 
3497     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
3498     auto& cur_icd_3 = env.get_test_icd(3);
3499     cur_icd_3.set_icd_api_version(VK_API_VERSION_1_1);
3500     cur_icd_3.physical_devices.push_back({"pd7"});
3501     cur_icd_3.physical_devices.back().extensions.push_back({VK_EXT_PCI_BUS_INFO_EXTENSION_NAME, 0});
3502     FillInRandomDeviceProps(cur_icd_3.physical_devices.back().properties, VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU, VK_API_VERSION_1_1,
3503                             6940, 0xDDDD001);
3504 
3505     InstWrapper inst(env.vulkan_functions);
3506     inst.create_info.set_api_version(VK_API_VERSION_1_1);
3507     inst.CheckCreate();
3508 
3509     PFN_vkGetPhysicalDeviceProperties2 GetPhysDevProps2 = inst.load("vkGetPhysicalDeviceProperties2");
3510     ASSERT_NE(GetPhysDevProps2, nullptr);
3511 
3512     const uint32_t max_phys_devs = 8;
3513     uint32_t device_count = max_phys_devs;
3514     std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
3515     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &device_count, physical_devices.data()));
3516     ASSERT_EQ(device_count, max_phys_devs);
3517 
3518     const uint32_t max_phys_dev_groups = 6;
3519     uint32_t group_count = max_phys_dev_groups;
3520     std::array<VkPhysicalDeviceGroupProperties, max_phys_dev_groups> physical_device_groups{};
3521     for (auto& group : physical_device_groups) group.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES;
3522 
3523     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &group_count, physical_device_groups.data()));
3524     ASSERT_EQ(group_count, max_phys_dev_groups);
3525 
3526     // make sure the order is what we started with - but its a bit wonky due to the loader reading physical devices "backwards"
3527     VkPhysicalDeviceProperties props{};
3528     inst->vkGetPhysicalDeviceProperties(physical_devices[0], &props);
3529     ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU);
3530     ASSERT_STREQ(props.deviceName, "pd7");
3531 
3532     inst->vkGetPhysicalDeviceProperties(physical_devices[1], &props);
3533     ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
3534     ASSERT_STREQ(props.deviceName, "pd4");
3535 
3536     inst->vkGetPhysicalDeviceProperties(physical_devices[2], &props);
3537     ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
3538     ASSERT_STREQ(props.deviceName, "pd5");
3539 
3540     inst->vkGetPhysicalDeviceProperties(physical_devices[3], &props);
3541     ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
3542     ASSERT_STREQ(props.deviceName, "pd6");
3543 
3544     inst->vkGetPhysicalDeviceProperties(physical_devices[4], &props);
3545     ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_CPU);
3546     ASSERT_STREQ(props.deviceName, "pd3");
3547 
3548     inst->vkGetPhysicalDeviceProperties(physical_devices[5], &props);
3549     ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
3550     ASSERT_STREQ(props.deviceName, "pd0");
3551 
3552     inst->vkGetPhysicalDeviceProperties(physical_devices[6], &props);
3553     ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU);
3554     ASSERT_STREQ(props.deviceName, "pd1");
3555 
3556     inst->vkGetPhysicalDeviceProperties(physical_devices[7], &props);
3557     ASSERT_EQ(props.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
3558     ASSERT_STREQ(props.deviceName, "pd2");
3559 
3560     // Make sure if we call enumerate again, the information is the same
3561     std::array<VkPhysicalDeviceGroupProperties, max_phys_dev_groups> physical_device_groups_again{};
3562     for (auto& group : physical_device_groups_again) group.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES;
3563 
3564     ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &group_count, physical_device_groups_again.data()));
3565     ASSERT_EQ(group_count, max_phys_dev_groups);
3566     for (uint32_t group = 0; group < max_phys_dev_groups; ++group) {
3567         ASSERT_EQ(physical_device_groups[group].physicalDeviceCount, physical_device_groups_again[group].physicalDeviceCount);
3568         for (uint32_t dev = 0; dev < physical_device_groups[group].physicalDeviceCount; ++dev) {
3569             ASSERT_EQ(physical_device_groups[group].physicalDevices[dev], physical_device_groups_again[group].physicalDevices[dev]);
3570         }
3571     }
3572 }
3573 
3574 #endif  // __linux__ || __FreeBSD__ || __OpenBSD__ || __GNU__
3575 
3576 const char* portability_driver_warning =
3577     "vkCreateInstance: Found drivers that contain devices which support the portability subset, but "
3578     "the instance does not enumerate portability drivers! Applications that wish to enumerate portability "
3579     "drivers must set the VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR bit in the VkInstanceCreateInfo "
3580     "flags and enable the VK_KHR_portability_enumeration instance extension.";
3581 
3582 const char* portability_flag_missing =
3583     "vkCreateInstance: Found drivers that contain devices which support the portability subset, but "
3584     "the instance does not enumerate portability drivers! Applications that wish to enumerate portability "
3585     "drivers must set the VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR bit in the VkInstanceCreateInfo "
3586     "flags.";
3587 
3588 const char* portability_extension_missing =
3589     "VkInstanceCreateInfo: If flags has the VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR bit set, the "
3590     "list of enabled extensions in ppEnabledExtensionNames must contain VK_KHR_portability_enumeration "
3591     "[VUID-VkInstanceCreateInfo-flags-06559 ]"
3592     "Applications that wish to enumerate portability drivers must enable the VK_KHR_portability_enumeration "
3593     "instance extension.";
3594 
TEST(PortabilityICDConfiguration,PortabilityICDOnly)3595 TEST(PortabilityICDConfiguration, PortabilityICDOnly) {
3596     FrameworkEnvironment env{};
3597     env.add_icd(
3598            TestICDDetails(ManifestICD{}.set_lib_path(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_is_portability_driver(true)))
3599         .add_physical_device("physical_device_0")
3600         .set_max_icd_interface_version(1);
3601     {  // enable portability extension and flag
3602         InstWrapper inst{env.vulkan_functions};
3603         inst.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
3604         inst.create_info.add_extension("VK_KHR_portability_enumeration");
3605         inst.create_info.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
3606         FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
3607         inst.CheckCreate();
3608         ASSERT_FALSE(env.debug_log.find(portability_driver_warning));
3609 
3610         DebugUtilsWrapper log{inst, VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
3611         CreateDebugUtilsMessenger(log);
3612 
3613         auto phys_dev = inst.GetPhysDev();
3614         handle_assert_has_value(phys_dev);
3615 
3616         DeviceWrapper dev_info{inst};
3617         dev_info.CheckCreate(phys_dev);
3618         ASSERT_FALSE(log.find(portability_driver_warning));
3619         ASSERT_FALSE(log.find(portability_flag_missing));
3620         ASSERT_FALSE(log.find(portability_extension_missing));
3621     }
3622     {  // enable portability flag but not extension - shouldn't be able to create an instance when filtering is enabled
3623         InstWrapper inst{env.vulkan_functions};
3624         inst.create_info.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
3625         inst.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
3626         FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
3627         inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER);
3628         ASSERT_TRUE(env.debug_log.find(portability_extension_missing));
3629     }
3630     {  // enable portability extension but not flag - shouldn't be able to create an instance when filtering is enabled
3631         InstWrapper inst{env.vulkan_functions};
3632         inst.create_info.add_extension("VK_KHR_portability_enumeration");
3633         inst.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
3634         FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
3635         inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER);
3636         ASSERT_TRUE(env.debug_log.find(portability_flag_missing));
3637     }
3638     {  // enable neither the portability extension or the flag - shouldn't be able to create an instance when filtering is enabled
3639         InstWrapper inst{env.vulkan_functions};
3640         inst.create_info.flags = 0;  // make sure its 0 - no portability
3641         inst.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
3642         FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
3643         inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER);
3644         ASSERT_TRUE(env.debug_log.find(portability_driver_warning));
3645     }
3646 }
3647 
TEST(PortabilityICDConfiguration,PortabilityAndRegularICD)3648 TEST(PortabilityICDConfiguration, PortabilityAndRegularICD) {
3649     FrameworkEnvironment env{};
3650     env.add_icd(TestICDDetails(ManifestICD{}.set_lib_path(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)));
3651     env.add_icd(
3652         TestICDDetails(ManifestICD{}.set_lib_path(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_is_portability_driver(true)));
3653 
3654     auto& driver0 = env.get_test_icd(0);
3655     auto& driver1 = env.get_test_icd(1);
3656 
3657     driver0.physical_devices.emplace_back("physical_device_0");
3658     driver0.max_icd_interface_version = 1;
3659 
3660     driver1.physical_devices.emplace_back("portability_physical_device_1");
3661     driver1.max_icd_interface_version = 1;
3662     {  // enable portability extension and flag
3663         InstWrapper inst{env.vulkan_functions};
3664         inst.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
3665         inst.create_info.add_extension("VK_KHR_portability_enumeration");
3666         inst.create_info.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
3667         FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
3668         inst.CheckCreate();
3669         ASSERT_FALSE(env.debug_log.find(portability_driver_warning));
3670 
3671         DebugUtilsWrapper log{inst, VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
3672         CreateDebugUtilsMessenger(log);
3673 
3674         auto phys_devs = inst.GetPhysDevs(2);
3675         for (const auto& phys_dev : phys_devs) {
3676             handle_assert_has_value(phys_dev);
3677         }
3678         DeviceWrapper dev_info_0{inst};
3679         DeviceWrapper dev_info_1{inst};
3680         dev_info_0.CheckCreate(phys_devs[0]);
3681         dev_info_1.CheckCreate(phys_devs[1]);
3682     }
3683     {  // enable portability extension but not flag - should only enumerate 1 physical device when filtering is enabled
3684         InstWrapper inst{env.vulkan_functions};
3685         inst.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
3686         inst.create_info.add_extension("VK_KHR_portability_enumeration");
3687         FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
3688         inst.CheckCreate();
3689         ASSERT_FALSE(env.debug_log.find(portability_driver_warning));
3690 
3691         DebugUtilsWrapper log{inst, VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
3692         CreateDebugUtilsMessenger(log);
3693         auto phys_dev = inst.GetPhysDev();
3694         handle_assert_has_value(phys_dev);
3695         DeviceWrapper dev_info_0{inst};
3696         dev_info_0.CheckCreate(phys_dev);
3697     }
3698     {  // enable portability flag but not extension - should only enumerate 1 physical device when filtering is enabled
3699         InstWrapper inst{env.vulkan_functions};
3700         inst.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
3701         inst.create_info.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
3702         FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
3703         inst.CheckCreate();
3704         ASSERT_FALSE(env.debug_log.find(portability_driver_warning));
3705 
3706         DebugUtilsWrapper log{inst, VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
3707         CreateDebugUtilsMessenger(log);
3708         auto phys_dev = inst.GetPhysDev();
3709         handle_assert_has_value(phys_dev);
3710         DeviceWrapper dev_info_0{inst};
3711         dev_info_0.CheckCreate(phys_dev);
3712     }
3713     {  // do not enable portability extension or flag - should only enumerate 1 physical device when filtering is enabled
3714         InstWrapper inst{env.vulkan_functions};
3715         inst.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
3716         FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
3717         inst.CheckCreate();
3718         ASSERT_FALSE(env.debug_log.find(portability_driver_warning));
3719 
3720         DebugUtilsWrapper log{inst, VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
3721         CreateDebugUtilsMessenger(log);
3722         auto phys_dev = inst.GetPhysDev();
3723         handle_assert_has_value(phys_dev);
3724         DeviceWrapper dev_info_0{inst};
3725         dev_info_0.CheckCreate(phys_dev);
3726     }
3727 }
3728 
3729 // Check that the portability enumeration flag bit doesn't get passed down
TEST(PortabilityICDConfiguration,PortabilityAndRegularICDCheckFlagsPassedIntoICD)3730 TEST(PortabilityICDConfiguration, PortabilityAndRegularICDCheckFlagsPassedIntoICD) {
3731     FrameworkEnvironment env{};
3732     env.add_icd(TestICDDetails(ManifestICD{}.set_lib_path(TEST_ICD_PATH_VERSION_2)));
3733     env.add_icd(TestICDDetails(ManifestICD{}.set_lib_path(TEST_ICD_PATH_VERSION_2).set_is_portability_driver(true)));
3734 
3735     auto& driver0 = env.get_test_icd(0);
3736     auto& driver1 = env.get_test_icd(1);
3737 
3738     driver0.physical_devices.emplace_back("physical_device_0");
3739     driver0.max_icd_interface_version = 1;
3740 
3741     driver1.physical_devices.emplace_back("portability_physical_device_1");
3742     driver1.add_instance_extension("VK_KHR_portability_enumeration");
3743     driver1.max_icd_interface_version = 1;
3744 
3745     InstWrapper inst{env.vulkan_functions};
3746     inst.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
3747     inst.create_info.add_extension("VK_KHR_portability_enumeration");
3748     inst.create_info.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR | 4;
3749 
3750     FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
3751     inst.CheckCreate();
3752     ASSERT_FALSE(env.debug_log.find(portability_driver_warning));
3753 
3754     ASSERT_EQ(static_cast<VkInstanceCreateFlags>(4), driver0.passed_in_instance_create_flags);
3755     ASSERT_EQ(VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR | static_cast<VkInstanceCreateFlags>(4),
3756               driver1.passed_in_instance_create_flags);
3757 }
3758 
TEST(PortabilityICDConfiguration,PortabilityAndRegularICDPreInstanceFunctions)3759 TEST(PortabilityICDConfiguration, PortabilityAndRegularICDPreInstanceFunctions) {
3760     FrameworkEnvironment env{};
3761     Extension first_ext{"VK_EXT_validation_features"};  // known instance extensions
3762     Extension second_ext{"VK_EXT_headless_surface"};
3763     env.add_icd(TestICDDetails(ManifestICD{}.set_lib_path(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)))
3764         .add_physical_device("physical_device_0")
3765         .set_max_icd_interface_version(1)
3766         .add_instance_extensions({first_ext, second_ext});
3767     env.add_icd(
3768            TestICDDetails(ManifestICD{}.set_lib_path(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_is_portability_driver(true)))
3769         .add_physical_device("portability_physical_device_1")
3770         .set_max_icd_interface_version(1);
3771     {
3772         // check that enumerating instance extensions work with a portability driver present
3773         auto extensions = env.GetInstanceExtensions(6);
3774         EXPECT_TRUE(string_eq(extensions.at(0).extensionName, first_ext.extensionName.c_str()));
3775         EXPECT_TRUE(string_eq(extensions.at(1).extensionName, second_ext.extensionName.c_str()));
3776         EXPECT_TRUE(string_eq(extensions.at(2).extensionName, VK_EXT_DEBUG_REPORT_EXTENSION_NAME));
3777         EXPECT_TRUE(string_eq(extensions.at(3).extensionName, VK_EXT_DEBUG_UTILS_EXTENSION_NAME));
3778         EXPECT_TRUE(string_eq(extensions.at(4).extensionName, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME));
3779         EXPECT_TRUE(string_eq(extensions.at(5).extensionName, VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME));
3780     }
3781 
3782     const char* layer_name = "TestLayer";
3783     env.add_explicit_layer(
3784         ManifestLayer{}.add_layer(
3785             ManifestLayer::LayerDescription{}.set_name(layer_name).set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)),
3786         "test_layer.json");
3787 
3788     InstWrapper inst{env.vulkan_functions};
3789     inst.create_info.add_layer(layer_name);
3790     inst.CheckCreate();
3791 
3792     VkPhysicalDevice phys_dev = inst.GetPhysDev();
3793     {  // LayersMatch
3794         auto layer_props = inst.GetActiveLayers(phys_dev, 1);
3795         ASSERT_TRUE(string_eq(layer_props.at(0).layerName, layer_name));
3796     }
3797     {  // Property count less than available
3798         VkLayerProperties layer_props;
3799         uint32_t layer_count = 0;
3800         ASSERT_EQ(VK_INCOMPLETE, env.vulkan_functions.vkEnumerateDeviceLayerProperties(phys_dev, &layer_count, &layer_props));
3801         ASSERT_EQ(layer_count, 0U);
3802     }
3803 }
3804 
3805 #if defined(_WIN32)
TEST(AppPackageDiscovery,AppPackageDrivers)3806 TEST(AppPackageDiscovery, AppPackageDrivers) {
3807     FrameworkEnvironment env;
3808     env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_2}.set_discovery_type(ManifestDiscoveryType::windows_app_package))
3809         .add_physical_device({});
3810 
3811     InstWrapper inst{env.vulkan_functions};
3812     inst.CheckCreate();
3813 }
TEST(AppPackageDiscovery,AppPackageLayers)3814 TEST(AppPackageDiscovery, AppPackageLayers) {
3815     FrameworkEnvironment env{};
3816     env.add_icd(TestICDDetails(ManifestICD{}.set_lib_path(TEST_ICD_PATH_VERSION_2))).add_physical_device({});
3817 
3818     const char* layer_name = "VK_LAYER_test_package_layer";
3819     env.add_implicit_layer(TestLayerDetails(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
3820                                                                           .set_name(layer_name)
3821                                                                           .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
3822                                                                           .set_disable_environment("DISABLE_ME")),
3823                                             "test_package_layer.json")
3824                                .set_discovery_type(ManifestDiscoveryType::windows_app_package));
3825 
3826     InstWrapper inst{env.vulkan_functions};
3827     inst.CheckCreate();
3828 
3829     auto layers = inst.GetActiveLayers(inst.GetPhysDev(), 1U);
3830     ASSERT_EQ(layers.size(), 1);
3831     ASSERT_TRUE(string_eq(layers.at(0).layerName, layer_name));
3832 }
3833 
TEST(AppPackageDiscovery,AppPackageICDAndLayers)3834 TEST(AppPackageDiscovery, AppPackageICDAndLayers) {
3835     FrameworkEnvironment env{};
3836     env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_2}.set_discovery_type(ManifestDiscoveryType::windows_app_package))
3837         .add_physical_device({});
3838 
3839     const char* layer_name = "VK_LAYER_test_package_layer";
3840     env.add_implicit_layer(TestLayerDetails(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
3841                                                                           .set_name(layer_name)
3842                                                                           .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
3843                                                                           .set_disable_environment("DISABLE_ME")),
3844                                             "test_package_layer.json")
3845                                .set_discovery_type(ManifestDiscoveryType::windows_app_package));
3846 
3847     InstWrapper inst{env.vulkan_functions};
3848     inst.CheckCreate();
3849 
3850     auto layers = inst.GetActiveLayers(inst.GetPhysDev(), 1U);
3851     ASSERT_EQ(layers.size(), 1);
3852     ASSERT_TRUE(string_eq(layers.at(0).layerName, layer_name));
3853 }
3854 
3855 // Make sure that stale layer manifests (path to nonexistant file) which have the same name as real manifests don't cause the real
3856 // manifests to be skipped. Stale registry entries happen when a registry is written on layer/driver installation but not cleaned up
3857 // when the corresponding manifest is removed from the file system.
TEST(DuplicateRegistryEntries,Layers)3858 TEST(DuplicateRegistryEntries, Layers) {
3859     FrameworkEnvironment env{};
3860     env.add_icd(TestICDDetails(ManifestICD{}.set_lib_path(TEST_ICD_PATH_VERSION_2)));
3861 
3862     auto null_path = env.get_folder(ManifestLocation::null).location() / "test_layer.json";
3863 
3864     env.platform_shim->add_manifest(ManifestCategory::explicit_layer, null_path);
3865 
3866     const char* layer_name = "TestLayer";
3867     env.add_explicit_layer(
3868         ManifestLayer{}.add_layer(
3869             ManifestLayer::LayerDescription{}.set_name(layer_name).set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)),
3870         "test_layer.json");
3871 
3872     InstWrapper inst{env.vulkan_functions};
3873     inst.create_info.add_layer(layer_name);
3874     inst.CheckCreate();
3875 }
3876 
3877 // Check that the de-duplication of drivers found in both PnP and generic Khronos/Vulkan/Drivers doesn't result in the same thing
3878 // being added twice
TEST(DuplicateRegistryEntries,Drivers)3879 TEST(DuplicateRegistryEntries, Drivers) {
3880     FrameworkEnvironment env{};
3881     auto null_path = env.get_folder(ManifestLocation::null).location() / "test_icd_0.json";
3882     env.platform_shim->add_manifest(ManifestCategory::icd, null_path);
3883 
3884     env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA}.set_discovery_type(ManifestDiscoveryType::null_dir))
3885         .add_physical_device("physical_device_0")
3886         .set_adapterLUID(_LUID{10, 1000});
3887     env.platform_shim->add_d3dkmt_adapter(D3DKMT_Adapter{0, _LUID{10, 1000}}.add_driver_manifest_path(env.get_icd_manifest_path()));
3888 
3889     InstWrapper inst{env.vulkan_functions};
3890     FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
3891     inst.CheckCreate();
3892     ASSERT_TRUE(env.debug_log.find(std::string("Skipping adding of json file \"") + null_path.string() +
3893                                    "\" from registry \"HKEY_LOCAL_MACHINE\\" VK_DRIVERS_INFO_REGISTRY_LOC
3894                                    "\" to the list due to duplication"));
3895 }
3896 #endif
3897 
TEST(LibraryLoading,SystemLocations)3898 TEST(LibraryLoading, SystemLocations) {
3899     FrameworkEnvironment env{};
3900     EnvVarWrapper ld_library_path("LD_LIBRARY_PATH", env.get_folder(ManifestLocation::driver).location().string());
3901     ld_library_path.add_to_list(env.get_folder(ManifestLocation::explicit_layer).location());
3902 
3903     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2).set_library_path_type(LibraryPathType::default_search_paths))
3904                        .add_physical_device({});
3905     const char* fake_ext_name = "VK_FAKE_extension";
3906     driver.physical_devices.back().add_extension(fake_ext_name);
3907 
3908     const char* layer_name = "TestLayer";
3909     env.add_explicit_layer(
3910         TestLayerDetails{ManifestLayer{}.add_layer(
3911                              ManifestLayer::LayerDescription{}.set_name(layer_name).set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)),
3912                          "test_layer.json"}
3913             .set_library_path_type(LibraryPathType::default_search_paths));
3914 
3915     auto props = env.GetLayerProperties(1);
3916     ASSERT_TRUE(string_eq(props.at(0).layerName, layer_name));
3917 
3918     InstWrapper inst{env.vulkan_functions};
3919     inst.create_info.add_layer(layer_name);
3920     FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
3921     inst.CheckCreate();
3922 
3923     auto phys_dev = inst.GetPhysDev();
3924 
3925     auto active_props = inst.GetActiveLayers(phys_dev, 1);
3926     ASSERT_TRUE(string_eq(active_props.at(0).layerName, layer_name));
3927 
3928     auto device_extensions = inst.EnumerateDeviceExtensions(phys_dev, 1);
3929     ASSERT_TRUE(string_eq(device_extensions.at(0).extensionName, fake_ext_name));
3930 }
3931 
3932 #if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__)
3933 // Check that valid symlinks do not cause the loader to crash when directly in an XDG env-var
TEST(ManifestDiscovery,ValidSymlinkInXDGEnvVar)3934 TEST(ManifestDiscovery, ValidSymlinkInXDGEnvVar) {
3935     FrameworkEnvironment env{FrameworkSettings{}.set_enable_default_search_paths(false)};
3936     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_discovery_type(ManifestDiscoveryType::override_folder))
3937         .add_physical_device({});
3938     auto driver_path = env.get_icd_manifest_path(0);
3939     std::string symlink_name = "symlink_to_driver.json";
3940     std::filesystem::path symlink_path = env.get_folder(ManifestLocation::driver_env_var).location() / symlink_name;
3941     env.get_folder(ManifestLocation::driver_env_var).add_existing_file(symlink_name);
3942     int res = symlink(driver_path.c_str(), symlink_path.c_str());
3943     ASSERT_EQ(res, 0);
3944     EnvVarWrapper xdg_config_dirs_env_var{"XDG_CONFIG_DIRS", symlink_path};
3945 
3946     InstWrapper inst{env.vulkan_functions};
3947     FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
3948     inst.CheckCreate();
3949 }
3950 
3951 // Check that valid symlinks do not cause the loader to crash
TEST(ManifestDiscovery,ValidSymlink)3952 TEST(ManifestDiscovery, ValidSymlink) {
3953     FrameworkEnvironment env{FrameworkSettings{}.set_enable_default_search_paths(false)};
3954     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_discovery_type(ManifestDiscoveryType::override_folder))
3955         .add_physical_device({});
3956 
3957     auto driver_path = env.get_icd_manifest_path(0);
3958     std::string symlink_name = "symlink_to_driver.json";
3959     std::filesystem::path symlink_path = env.get_folder(ManifestLocation::driver_env_var).location() / symlink_name;
3960     env.get_folder(ManifestLocation::driver_env_var).add_existing_file(symlink_name);
3961     int res = symlink(driver_path.c_str(), symlink_path.c_str());
3962     ASSERT_EQ(res, 0);
3963 
3964     env.platform_shim->set_fake_path(ManifestCategory::icd, env.get_folder(ManifestLocation::driver_env_var).location());
3965 
3966     InstWrapper inst{env.vulkan_functions};
3967     FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
3968     inst.CheckCreate();
3969 }
3970 
3971 // Check that invalid symlinks do not cause the loader to crash when directly in an XDG env-var
TEST(ManifestDiscovery,InvalidSymlinkXDGEnvVar)3972 TEST(ManifestDiscovery, InvalidSymlinkXDGEnvVar) {
3973     FrameworkEnvironment env{FrameworkSettings{}.set_enable_default_search_paths(false)};
3974     std::string symlink_name = "symlink_to_nothing.json";
3975     std::filesystem::path symlink_path = env.get_folder(ManifestLocation::driver_env_var).location() / symlink_name;
3976     std::filesystem::path invalid_driver_path = env.get_folder(ManifestLocation::driver).location() / "nothing_here.json";
3977     int res = symlink(invalid_driver_path.c_str(), symlink_path.c_str());
3978     ASSERT_EQ(res, 0);
3979     env.get_folder(ManifestLocation::driver_env_var).add_existing_file(symlink_name);
3980 
3981     EnvVarWrapper xdg_config_dirs_env_var{symlink_path};
3982 
3983     InstWrapper inst{env.vulkan_functions};
3984     FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
3985     inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER);
3986 }
3987 
3988 // Check that invalid symlinks do not cause the loader to crash
TEST(ManifestDiscovery,InvalidSymlink)3989 TEST(ManifestDiscovery, InvalidSymlink) {
3990     FrameworkEnvironment env{FrameworkSettings{}.set_enable_default_search_paths(false)};
3991     std::string symlink_name = "symlink_to_nothing.json";
3992     std::filesystem::path symlink_path = env.get_folder(ManifestLocation::driver).location() / symlink_name;
3993     std::filesystem::path invalid_driver_path = env.get_folder(ManifestLocation::driver_env_var).location() / "nothing_here.json";
3994     int res = symlink(invalid_driver_path.c_str(), symlink_path.c_str());
3995     ASSERT_EQ(res, 0);
3996     env.get_folder(ManifestLocation::driver).add_existing_file(symlink_name);
3997 
3998     env.platform_shim->set_fake_path(ManifestCategory::icd, env.get_folder(ManifestLocation::driver_env_var).location());
3999 
4000     InstWrapper inst{env.vulkan_functions};
4001     FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
4002     inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER);
4003 }
4004 #endif
4005 
4006 #if defined(__APPLE__)
4007 // Add two drivers, one to the bundle and one to the system locations
TEST(ManifestDiscovery,AppleBundles)4008 TEST(ManifestDiscovery, AppleBundles) {
4009     FrameworkEnvironment env{};
4010     env.setup_macos_bundle();
4011     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_discovery_type(ManifestDiscoveryType::macos_bundle));
4012     env.get_test_icd(0).physical_devices.push_back({});
4013     env.get_test_icd(0).physical_devices.at(0).properties.deviceID = 1337;
4014     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
4015     env.get_test_icd(1).physical_devices.push_back({});
4016     env.get_test_icd(1).physical_devices.at(0).properties.deviceID = 9999;
4017 
4018     InstWrapper inst{env.vulkan_functions};
4019     ASSERT_NO_FATAL_FAILURE(inst.CheckCreate());
4020     auto physical_devices = inst.GetPhysDevs();
4021     ASSERT_EQ(1, physical_devices.size());
4022 
4023     // Verify that this is the 'right' GPU, aka the one from the bundle
4024     VkPhysicalDeviceProperties props{};
4025     inst->vkGetPhysicalDeviceProperties(physical_devices[0], &props);
4026     ASSERT_EQ(env.get_test_icd(0).physical_devices.at(0).properties.deviceID, props.deviceID);
4027 }
4028 
4029 // Add two drivers, one to the bundle and one using the driver env-var
TEST(ManifestDiscovery,AppleBundlesEnvVarActive)4030 TEST(ManifestDiscovery, AppleBundlesEnvVarActive) {
4031     FrameworkEnvironment env{};
4032     env.setup_macos_bundle();
4033     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_discovery_type(ManifestDiscoveryType::macos_bundle));
4034     env.get_test_icd(0).physical_devices.push_back({});
4035     env.get_test_icd(0).physical_devices.at(0).properties.deviceID = 1337;
4036     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_discovery_type(ManifestDiscoveryType::env_var));
4037     env.get_test_icd(1).physical_devices.push_back({});
4038     env.get_test_icd(1).physical_devices.at(0).properties.deviceID = 9999;
4039 
4040     InstWrapper inst{env.vulkan_functions};
4041     ASSERT_NO_FATAL_FAILURE(inst.CheckCreate());
4042     auto physical_devices = inst.GetPhysDevs();
4043     ASSERT_EQ(1, physical_devices.size());
4044 
4045     // Verify that this is the 'right' GPU, aka the one from the env-var
4046     VkPhysicalDeviceProperties props{};
4047     inst->vkGetPhysicalDeviceProperties(physical_devices[0], &props);
4048     ASSERT_EQ(env.get_test_icd(1).physical_devices.at(0).properties.deviceID, props.deviceID);
4049 }
4050 #endif
4051 
TEST(LayerCreatesDevice,Basic)4052 TEST(LayerCreatesDevice, Basic) {
4053     FrameworkEnvironment env{};
4054     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device({});
4055 
4056     env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
4057                                                          .set_name("implicit_layer_name")
4058                                                          .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
4059                                                          .set_disable_environment("DISABLE_ME")),
4060                            "implicit_test_layer.json");
4061     env.get_test_layer().set_call_create_device_while_create_device_is_called(true);
4062     env.get_test_layer().set_physical_device_index_to_use_during_create_device(0);
4063 
4064     env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
4065                                                          .set_name("implicit_layer_name2")
4066                                                          .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
4067                                                          .set_disable_environment("DISABLE_ME")),
4068                            "implicit_test_layer2.json");
4069 
4070     InstWrapper inst{env.vulkan_functions};
4071     inst.CheckCreate();
4072 
4073     DeviceWrapper dev{inst};
4074     dev.CheckCreate(inst.GetPhysDev());
4075 }
4076 
TEST(LayerCreatesDevice,DifferentPhysicalDevice)4077 TEST(LayerCreatesDevice, DifferentPhysicalDevice) {
4078     FrameworkEnvironment env{};
4079     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
4080     env.get_test_icd(0).physical_devices.emplace_back("Device0");
4081     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
4082     env.get_test_icd(1).physical_devices.emplace_back("Device1");
4083 
4084     env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
4085                                                          .set_name("implicit_layer_name")
4086                                                          .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
4087                                                          .set_disable_environment("DISABLE_ME")),
4088                            "implicit_test_layer.json");
4089     env.get_test_layer().set_call_create_device_while_create_device_is_called(true);
4090     env.get_test_layer().set_physical_device_index_to_use_during_create_device(1);
4091 
4092     env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
4093                                                          .set_name("implicit_layer_name2")
4094                                                          .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
4095                                                          .set_disable_environment("DISABLE_ME")),
4096                            "implicit_test_layer2.json");
4097 
4098     InstWrapper inst{env.vulkan_functions};
4099     inst.CheckCreate();
4100 
4101     auto phys_devs = inst.GetPhysDevs();
4102 
4103     DeviceWrapper dev{inst};
4104     dev.CheckCreate(phys_devs.at(0));
4105 }
4106 
TEST(Layer,pfnNextGetInstanceProcAddr_should_not_return_layers_own_functions)4107 TEST(Layer, pfnNextGetInstanceProcAddr_should_not_return_layers_own_functions) {
4108     FrameworkEnvironment env{};
4109     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device({});
4110 
4111     env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
4112                                                          .set_name("implicit_layer_name")
4113                                                          .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
4114                                                          .set_disable_environment("DISABLE_ME")),
4115                            "implicit_test_layer.json");
4116     env.get_test_layer(0).set_check_if_EnumDevExtProps_is_same_as_queried_function(true);
4117 
4118     InstWrapper inst{env.vulkan_functions};
4119     inst.CheckCreate();
4120 
4121     auto phys_devs = inst.GetPhysDevs();
4122 
4123     DeviceWrapper dev{inst};
4124     dev.CheckCreate(phys_devs.at(0));
4125 }
4126 
TEST(Layer,LLP_LAYER_21)4127 TEST(Layer, LLP_LAYER_21) {
4128     FrameworkEnvironment env{};
4129     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device({});
4130 
4131     env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
4132                                                          .set_name("implicit_layer_name")
4133                                                          .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
4134                                                          .set_disable_environment("DISABLE_ME")),
4135                            "implicit_test_layer.json");
4136     env.get_test_layer(0).set_clobber_pInstance(true);
4137 
4138     InstWrapper inst{env.vulkan_functions};
4139     FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
4140 #if defined(WIN32)
4141 #if defined(_WIN64)
4142     ASSERT_DEATH(
4143         inst.CheckCreate(),
4144         testing::ContainsRegex(
4145             R"(terminator_CreateInstance: Instance pointer \(................\) has invalid MAGIC value 0x00000000. Instance value )"
4146             R"(possibly corrupted by active layer \(Policy #LLP_LAYER_21\))"));
4147 #else
4148     ASSERT_DEATH(
4149         inst.CheckCreate(),
4150         testing::ContainsRegex(
4151             R"(terminator_CreateInstance: Instance pointer \(........\) has invalid MAGIC value 0x00000000. Instance value )"
4152             R"(possibly corrupted by active layer \(Policy #LLP_LAYER_21\))"));
4153 #endif
4154 #else
4155     ASSERT_DEATH(
4156         inst.CheckCreate(),
4157         testing::ContainsRegex(
4158             R"(terminator_CreateInstance: Instance pointer \(0x[0-9A-Fa-f]+\) has invalid MAGIC value 0x00000000. Instance value )"
4159             R"(possibly corrupted by active layer \(Policy #LLP_LAYER_21\))"));
4160 #endif
4161 }
4162 
TEST(Layer,LLP_LAYER_22)4163 TEST(Layer, LLP_LAYER_22) {
4164     FrameworkEnvironment env{};
4165     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device({});
4166 
4167     env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
4168                                                          .set_name("implicit_layer_name")
4169                                                          .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
4170                                                          .set_disable_environment("DISABLE_ME")),
4171                            "implicit_test_layer.json");
4172     env.get_test_layer(0).set_clobber_pDevice(true);
4173 
4174     InstWrapper inst{env.vulkan_functions};
4175     inst.create_info.add_extension("VK_EXT_debug_utils");
4176     inst.CheckCreate();
4177 
4178     DebugUtilsWrapper log{inst};
4179     CreateDebugUtilsMessenger(log);
4180 
4181     DeviceWrapper dev{inst};
4182 #if defined(WIN32)
4183 #if defined(_WIN64)
4184     ASSERT_DEATH(
4185         dev.CheckCreate(inst.GetPhysDev()),
4186         testing::ContainsRegex(
4187             R"(terminator_CreateDevice: Device pointer \(................\) has invalid MAGIC value 0x00000000. The expected value is 0x10ADED040410ADED. Device value )"
4188             R"(possibly corrupted by active layer \(Policy #LLP_LAYER_22\))"));
4189 #else
4190     ASSERT_DEATH(
4191         dev.CheckCreate(inst.GetPhysDev()),
4192         testing::ContainsRegex(
4193             R"(terminator_CreateDevice: Device pointer \(........\) has invalid MAGIC value 0x00000000. The expected value is 0x10ADED040410ADED. Device value )"
4194             R"(possibly corrupted by active layer \(Policy #LLP_LAYER_22\))"));
4195 #endif
4196 #else
4197     ASSERT_DEATH(
4198         dev.CheckCreate(inst.GetPhysDev()),
4199         testing::ContainsRegex(
4200             R"(terminator_CreateDevice: Device pointer \(0x[0-9A-Fa-f]+\) has invalid MAGIC value 0x00000000. The expected value is 0x10ADED040410ADED. Device value )"
4201             R"(possibly corrupted by active layer \(Policy #LLP_LAYER_22\))"));
4202 #endif
4203 }
4204 
TEST(InvalidManifest,ICD)4205 TEST(InvalidManifest, ICD) {
4206     FrameworkEnvironment env{};
4207     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device({});
4208 
4209     std::vector<std::string> invalid_jsons;
4210     invalid_jsons.push_back(",");
4211     invalid_jsons.push_back("{},[]");
4212     invalid_jsons.push_back("{ \"foo\":\"bar\", }");
4213     invalid_jsons.push_back("{\"foo\":\"bar\", \"baz\": [], },");
4214     invalid_jsons.push_back("{\"foo\":\"bar\", \"baz\": [{},] },");
4215     invalid_jsons.push_back("{\"foo\":\"bar\", \"baz\": {\"fee\"} },");
4216     invalid_jsons.push_back("{\"\":\"bar\", \"baz\": {}");
4217     invalid_jsons.push_back("{\"foo\":\"bar\", \"baz\": {\"fee\":1234, true, \"ab\":\"bc\"} },");
4218 
4219     for (size_t i = 0; i < invalid_jsons.size(); i++) {
4220         auto file_name = std::string("invalid_driver_") + std::to_string(i) + ".json";
4221         std::filesystem::path new_path = env.get_folder(ManifestLocation::driver).write_manifest(file_name, invalid_jsons[i]);
4222         env.platform_shim->add_manifest(ManifestCategory::icd, new_path);
4223     }
4224 
4225     InstWrapper inst{env.vulkan_functions};
4226     inst.CheckCreate();
4227 }
4228 
TEST(InvalidManifest,Layer)4229 TEST(InvalidManifest, Layer) {
4230     FrameworkEnvironment env{};
4231     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device({});
4232 
4233     std::vector<std::string> invalid_jsons;
4234     invalid_jsons.push_back(",");
4235     invalid_jsons.push_back("{},[]");
4236     invalid_jsons.push_back("{ \"foo\":\"bar\", }");
4237     invalid_jsons.push_back("{\"foo\":\"bar\", \"baz\": [], },");
4238     invalid_jsons.push_back("{\"foo\":\"bar\", \"baz\": [{},] },");
4239     invalid_jsons.push_back("{\"foo\":\"bar\", \"baz\": {\"fee\"} },");
4240     invalid_jsons.push_back("{\"\":\"bar\", \"baz\": {}");
4241     invalid_jsons.push_back("{\"foo\":\"bar\", \"baz\": {\"fee\":1234, true, \"ab\":\"bc\"} },");
4242 
4243     for (size_t i = 0; i < invalid_jsons.size(); i++) {
4244         auto file_name = std::string("invalid_implicit_layer_") + std::to_string(i) + ".json";
4245         std::filesystem::path new_path =
4246             env.get_folder(ManifestLocation::implicit_layer).write_manifest(file_name, invalid_jsons[i]);
4247         env.platform_shim->add_manifest(ManifestCategory::implicit_layer, new_path);
4248     }
4249 
4250     InstWrapper inst{env.vulkan_functions};
4251     inst.CheckCreate();
4252 }
4253 #if defined(WIN32)
add_dxgi_adapter(FrameworkEnvironment & env,std::filesystem::path const & name,LUID luid,uint32_t vendor_id)4254 void add_dxgi_adapter(FrameworkEnvironment& env, std::filesystem::path const& name, LUID luid, uint32_t vendor_id) {
4255     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6).set_discovery_type(ManifestDiscoveryType::null_dir));
4256     driver.set_min_icd_interface_version(5);
4257     driver.set_max_icd_interface_version(6);
4258     driver.setup_WSI();
4259     driver.set_icd_api_version(VK_API_VERSION_1_1);
4260     driver.physical_devices.emplace_back(name.string());
4261     auto& pd0 = driver.physical_devices.back();
4262     pd0.properties.apiVersion = VK_API_VERSION_1_1;
4263     driver.set_adapterLUID(luid);
4264 
4265     // luid is unique per DXGI/D3DKMT adapters.Don't add extra DXGI device if one is already created.
4266     // Just add path icd path to matching d3dkmt_adapter.
4267     D3DKMT_Adapter* pAdapter = NULL;
4268     for (uint32_t i = 0; i < env.platform_shim->d3dkmt_adapters.size(); i++) {
4269         if (env.platform_shim->d3dkmt_adapters[i].adapter_luid.HighPart == luid.HighPart &&
4270             env.platform_shim->d3dkmt_adapters[i].adapter_luid.LowPart == luid.LowPart) {
4271             pAdapter = &env.platform_shim->d3dkmt_adapters[i];
4272             break;
4273         }
4274     }
4275     if (pAdapter == NULL) {
4276         DXGI_ADAPTER_DESC1 desc{};
4277         desc.VendorId = known_driver_list.at(vendor_id).vendor_id;
4278         desc.AdapterLuid = luid;
4279         wcsncpy_s(desc.Description, 128, name.c_str(), name.native().size());
4280         env.platform_shim->add_dxgi_adapter(GpuType::discrete, desc);
4281 
4282         env.platform_shim->add_d3dkmt_adapter(
4283             D3DKMT_Adapter{static_cast<UINT>(env.icds.size()) - 1U, desc.AdapterLuid}.add_driver_manifest_path(
4284                 env.get_icd_manifest_path(env.icds.size() - 1)));
4285     } else {
4286         pAdapter->add_driver_manifest_path(env.get_icd_manifest_path(env.icds.size() - 1));
4287     }
4288 }
4289 
TEST(EnumerateAdapterPhysicalDevices,SameAdapterLUID_reordered)4290 TEST(EnumerateAdapterPhysicalDevices, SameAdapterLUID_reordered) {
4291     FrameworkEnvironment env;
4292 
4293     uint32_t physical_count = 3;
4294 
4295     // Physical devices are enumerated:
4296     // a) first in the order of LUIDs showing up in DXGIAdapter list
4297     // b) then in the reverse order to the drivers insertion into the test framework
4298     add_dxgi_adapter(env, "physical_device_2", LUID{10, 100}, 2);
4299     add_dxgi_adapter(env, "physical_device_1", LUID{20, 200}, 1);
4300     add_dxgi_adapter(env, "physical_device_0", LUID{10, 100}, 2);
4301 
4302     {
4303         uint32_t returned_physical_count = 0;
4304         InstWrapper inst{env.vulkan_functions};
4305         inst.create_info.setup_WSI().set_api_version(VK_API_VERSION_1_1);
4306         inst.CheckCreate();
4307 
4308         ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, nullptr));
4309         ASSERT_EQ(physical_count, returned_physical_count);
4310         std::vector<VkPhysicalDevice> physical_device_handles{returned_physical_count};
4311         ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count,
4312                                                                               physical_device_handles.data()));
4313         ASSERT_EQ(physical_count, returned_physical_count);
4314 
4315         VkPhysicalDeviceProperties phys_dev_props[3]{};
4316         env.vulkan_functions.vkGetPhysicalDeviceProperties(physical_device_handles[0], &(phys_dev_props[0]));
4317         env.vulkan_functions.vkGetPhysicalDeviceProperties(physical_device_handles[1], &(phys_dev_props[1]));
4318         env.vulkan_functions.vkGetPhysicalDeviceProperties(physical_device_handles[2], &(phys_dev_props[2]));
4319 
4320         EXPECT_TRUE(string_eq(phys_dev_props[0].deviceName, "physical_device_0"));
4321         EXPECT_TRUE(string_eq(phys_dev_props[1].deviceName, "physical_device_2"));
4322         // Because LUID{10,100} is encountered first, all physical devices which correspond to that LUID are enumerated before any
4323         // other physical devices.
4324         EXPECT_TRUE(string_eq(phys_dev_props[2].deviceName, "physical_device_1"));
4325 
4326         // Check that both devices do not report VK_LAYERED_DRIVER_UNDERLYING_API_D3D12_MSFT
4327         VkPhysicalDeviceLayeredDriverPropertiesMSFT layered_driver_properties_msft{};
4328         layered_driver_properties_msft.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LAYERED_DRIVER_PROPERTIES_MSFT;
4329         VkPhysicalDeviceProperties2 props2{};
4330         props2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
4331         props2.pNext = (void*)&layered_driver_properties_msft;
4332 
4333         env.vulkan_functions.vkGetPhysicalDeviceProperties2(physical_device_handles[0], &props2);
4334         EXPECT_EQ(layered_driver_properties_msft.underlyingAPI, VK_LAYERED_DRIVER_UNDERLYING_API_NONE_MSFT);
4335 
4336         env.vulkan_functions.vkGetPhysicalDeviceProperties2(physical_device_handles[1], &props2);
4337         EXPECT_EQ(layered_driver_properties_msft.underlyingAPI, VK_LAYERED_DRIVER_UNDERLYING_API_NONE_MSFT);
4338 
4339         env.vulkan_functions.vkGetPhysicalDeviceProperties2(physical_device_handles[2], &props2);
4340         EXPECT_EQ(layered_driver_properties_msft.underlyingAPI, VK_LAYERED_DRIVER_UNDERLYING_API_NONE_MSFT);
4341     }
4342     // Set the first physical device that is enumerated to be a 'layered' driver so it should be swapped with the first physical
4343     // device
4344     env.get_test_icd(2).physical_devices.back().layered_driver_underlying_api = VK_LAYERED_DRIVER_UNDERLYING_API_D3D12_MSFT;
4345     {
4346         uint32_t returned_physical_count = 0;
4347         InstWrapper inst{env.vulkan_functions};
4348         inst.create_info.setup_WSI().set_api_version(VK_API_VERSION_1_1);
4349         inst.CheckCreate();
4350 
4351         ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, nullptr));
4352         ASSERT_EQ(physical_count, returned_physical_count);
4353         std::vector<VkPhysicalDevice> physical_device_handles{returned_physical_count};
4354         ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count,
4355                                                                               physical_device_handles.data()));
4356         ASSERT_EQ(physical_count, returned_physical_count);
4357 
4358         VkPhysicalDeviceProperties phys_dev_props[3]{};
4359         env.vulkan_functions.vkGetPhysicalDeviceProperties(physical_device_handles[0], &(phys_dev_props[0]));
4360         env.vulkan_functions.vkGetPhysicalDeviceProperties(physical_device_handles[1], &(phys_dev_props[1]));
4361         env.vulkan_functions.vkGetPhysicalDeviceProperties(physical_device_handles[2], &(phys_dev_props[2]));
4362 
4363         // Because the 'last' driver has the layered_driver set to D3D12, the order is modified
4364         EXPECT_TRUE(string_eq(phys_dev_props[0].deviceName, "physical_device_2"));
4365         EXPECT_TRUE(string_eq(phys_dev_props[1].deviceName, "physical_device_0"));
4366         // Because LUID{10,100} is encountered first, all physical devices which correspond to that LUID are enumerated before any
4367         // other physical devices.
4368         EXPECT_TRUE(string_eq(phys_dev_props[2].deviceName, "physical_device_1"));
4369 
4370         // Check that the correct physical device reports VK_LAYERED_DRIVER_UNDERLYING_API_D3D12_MSFT
4371         VkPhysicalDeviceLayeredDriverPropertiesMSFT layered_driver_properties_msft{};
4372         layered_driver_properties_msft.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LAYERED_DRIVER_PROPERTIES_MSFT;
4373         VkPhysicalDeviceProperties2 props2{};
4374         props2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
4375         props2.pNext = (void*)&layered_driver_properties_msft;
4376 
4377         env.vulkan_functions.vkGetPhysicalDeviceProperties2(physical_device_handles[0], &props2);
4378         EXPECT_EQ(layered_driver_properties_msft.underlyingAPI, VK_LAYERED_DRIVER_UNDERLYING_API_NONE_MSFT);
4379 
4380         env.vulkan_functions.vkGetPhysicalDeviceProperties2(physical_device_handles[1], &props2);
4381         EXPECT_EQ(layered_driver_properties_msft.underlyingAPI, VK_LAYERED_DRIVER_UNDERLYING_API_D3D12_MSFT);
4382 
4383         env.vulkan_functions.vkGetPhysicalDeviceProperties2(physical_device_handles[2], &props2);
4384         EXPECT_EQ(layered_driver_properties_msft.underlyingAPI, VK_LAYERED_DRIVER_UNDERLYING_API_NONE_MSFT);
4385     }
4386 }
4387 
TEST(EnumerateAdapterPhysicalDevices,SameAdapterLUID_same_order)4388 TEST(EnumerateAdapterPhysicalDevices, SameAdapterLUID_same_order) {
4389     FrameworkEnvironment env;
4390 
4391     uint32_t physical_count = 3;
4392 
4393     // Physical devices are enumerated:
4394     // a) first in the order of LUIDs showing up in DXGIAdapter list
4395     // b) then in the reverse order to the drivers insertion into the test framework
4396     add_dxgi_adapter(env, "physical_device_2", LUID{10, 100}, 2);
4397     add_dxgi_adapter(env, "physical_device_1", LUID{20, 200}, 1);
4398     add_dxgi_adapter(env, "physical_device_0", LUID{10, 100}, 2);
4399 
4400     // Set the last physical device that is enumerated last to be a 'layered'  physical device - no swapping should occur
4401     env.get_test_icd(0).physical_devices.back().layered_driver_underlying_api = VK_LAYERED_DRIVER_UNDERLYING_API_D3D12_MSFT;
4402 
4403     uint32_t returned_physical_count = 0;
4404     InstWrapper inst{env.vulkan_functions};
4405     inst.create_info.setup_WSI().set_api_version(VK_API_VERSION_1_1);
4406     inst.CheckCreate();
4407 
4408     ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, nullptr));
4409     ASSERT_EQ(physical_count, returned_physical_count);
4410     std::vector<VkPhysicalDevice> physical_device_handles{returned_physical_count};
4411     ASSERT_EQ(VK_SUCCESS,
4412               env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, physical_device_handles.data()));
4413     ASSERT_EQ(physical_count, returned_physical_count);
4414 
4415     VkPhysicalDeviceProperties phys_dev_props[3]{};
4416     env.vulkan_functions.vkGetPhysicalDeviceProperties(physical_device_handles[0], &(phys_dev_props[0]));
4417     env.vulkan_functions.vkGetPhysicalDeviceProperties(physical_device_handles[1], &(phys_dev_props[1]));
4418     env.vulkan_functions.vkGetPhysicalDeviceProperties(physical_device_handles[2], &(phys_dev_props[2]));
4419 
4420     // Make sure that reordering doesn't occur if the MSFT layered driver appears second
4421     EXPECT_TRUE(string_eq(phys_dev_props[0].deviceName, "physical_device_0"));
4422     EXPECT_TRUE(string_eq(phys_dev_props[1].deviceName, "physical_device_2"));
4423     // Because LUID{10,100} is encountered first, all physical devices which correspond to that LUID are enumerated before any
4424     // other physical devices.
4425     EXPECT_TRUE(string_eq(phys_dev_props[2].deviceName, "physical_device_1"));
4426 
4427     // Check that the correct physical device reports VK_LAYERED_DRIVER_UNDERLYING_API_D3D12_MSFT
4428     VkPhysicalDeviceLayeredDriverPropertiesMSFT layered_driver_properties_msft{};
4429     layered_driver_properties_msft.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LAYERED_DRIVER_PROPERTIES_MSFT;
4430     VkPhysicalDeviceProperties2 props2{};
4431     props2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
4432     props2.pNext = (void*)&layered_driver_properties_msft;
4433 
4434     env.vulkan_functions.vkGetPhysicalDeviceProperties2(physical_device_handles[0], &props2);
4435     EXPECT_EQ(layered_driver_properties_msft.underlyingAPI, VK_LAYERED_DRIVER_UNDERLYING_API_NONE_MSFT);
4436 
4437     env.vulkan_functions.vkGetPhysicalDeviceProperties2(physical_device_handles[1], &props2);
4438     EXPECT_EQ(layered_driver_properties_msft.underlyingAPI, VK_LAYERED_DRIVER_UNDERLYING_API_D3D12_MSFT);
4439 
4440     env.vulkan_functions.vkGetPhysicalDeviceProperties2(physical_device_handles[2], &props2);
4441     EXPECT_EQ(layered_driver_properties_msft.underlyingAPI, VK_LAYERED_DRIVER_UNDERLYING_API_NONE_MSFT);
4442 }
4443 
TEST(EnumerateAdapterPhysicalDevices,WrongErrorCodes)4444 TEST(EnumerateAdapterPhysicalDevices, WrongErrorCodes) {
4445     FrameworkEnvironment env;
4446 
4447     add_dxgi_adapter(env, "physical_device_0", LUID{10, 100}, 2);
4448     InstWrapper inst{env.vulkan_functions};
4449     inst.create_info.setup_WSI().set_api_version(VK_API_VERSION_1_1);
4450     inst.CheckCreate();
4451     // TestICD only fails in EnumAdapters, so shouldn't fail to query VkPhysicalDevices
4452     {
4453         env.get_test_icd().set_enum_adapter_physical_devices_return_code(VK_ERROR_INITIALIZATION_FAILED);
4454         uint32_t returned_physical_count = 0;
4455         EXPECT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, nullptr));
4456         EXPECT_EQ(returned_physical_count, 1);
4457     }
4458     {
4459         env.get_test_icd().set_enum_adapter_physical_devices_return_code(VK_ERROR_INCOMPATIBLE_DRIVER);
4460         uint32_t returned_physical_count = 0;
4461         EXPECT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, nullptr));
4462         EXPECT_EQ(returned_physical_count, 1);
4463     }
4464     {
4465         env.get_test_icd().set_enum_adapter_physical_devices_return_code(VK_ERROR_SURFACE_LOST_KHR);
4466         uint32_t returned_physical_count = 0;
4467         EXPECT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, nullptr));
4468         EXPECT_EQ(returned_physical_count, 1);
4469     }
4470 
4471     // TestICD fails in EnumPhysDevs, should return VK_ERROR_INCOMPATIBLE_DRIVER
4472     auto check_icds = [&env, &inst] {
4473         env.get_test_icd().set_enum_adapter_physical_devices_return_code(VK_ERROR_INITIALIZATION_FAILED);
4474         uint32_t returned_physical_count = 0;
4475         EXPECT_EQ(VK_ERROR_INITIALIZATION_FAILED,
4476                   env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, nullptr));
4477         EXPECT_EQ(returned_physical_count, 0);
4478 
4479         env.get_test_icd().set_enum_adapter_physical_devices_return_code(VK_ERROR_INCOMPATIBLE_DRIVER);
4480         returned_physical_count = 0;
4481         EXPECT_EQ(VK_ERROR_INITIALIZATION_FAILED,
4482                   env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, nullptr));
4483         EXPECT_EQ(returned_physical_count, 0);
4484 
4485         env.get_test_icd().set_enum_adapter_physical_devices_return_code(VK_ERROR_SURFACE_LOST_KHR);
4486         returned_physical_count = 0;
4487         EXPECT_EQ(VK_ERROR_INITIALIZATION_FAILED,
4488                   env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, nullptr));
4489         EXPECT_EQ(returned_physical_count, 0);
4490     };
4491 
4492     // TestICD fails in EnumPhysDevs, should return VK_ERROR_INCOMPATIBLE_DRIVER
4493     env.get_test_icd().set_enum_physical_devices_return_code(VK_ERROR_INITIALIZATION_FAILED);
4494     check_icds();
4495 
4496     // TestICD fails in EnumPhysDevs, should return VK_ERROR_INCOMPATIBLE_DRIVER
4497     env.get_test_icd().set_enum_physical_devices_return_code(VK_ERROR_INCOMPATIBLE_DRIVER);
4498     check_icds();
4499 
4500     // TestICD fails in EnumPhysDevs, should return VK_ERROR_INCOMPATIBLE_DRIVER
4501     env.get_test_icd().set_enum_physical_devices_return_code(VK_ERROR_SURFACE_LOST_KHR);
4502     check_icds();
4503 }
4504 
TEST(EnumerateAdapterPhysicalDevices,ManyAdapters)4505 TEST(EnumerateAdapterPhysicalDevices, ManyAdapters) {
4506     FrameworkEnvironment env;
4507 
4508     uint32_t icd_count = 10;
4509     for (uint32_t i = 0; i < icd_count; i++) {
4510         // Add 2 separate physical devices with the same luid
4511         LUID luid{10U + i, static_cast<LONG>(100U + i)};
4512         add_dxgi_adapter(env, std::string("physical_device_") + std::to_string(i), luid, 2);
4513         add_dxgi_adapter(env, std::string("physical_device_") + std::to_string(i + icd_count), luid, 2);
4514     }
4515     uint32_t device_count = icd_count * 2;
4516     InstWrapper inst{env.vulkan_functions};
4517     inst.create_info.setup_WSI().set_api_version(VK_API_VERSION_1_1);
4518     inst.CheckCreate();
4519 
4520     auto physical_devices = inst.GetPhysDevs(device_count);
4521     for (auto physical_device : physical_devices) {
4522         DeviceWrapper dev{inst};
4523         dev.CheckCreate(physical_device);
4524     }
4525 }
4526 #endif  // defined(WIN32)
4527 
try_create_swapchain(InstWrapper & inst,VkPhysicalDevice physical_device,DeviceWrapper & dev,VkSurfaceKHR const & surface)4528 void try_create_swapchain(InstWrapper& inst, VkPhysicalDevice physical_device, DeviceWrapper& dev, VkSurfaceKHR const& surface) {
4529     PFN_vkGetPhysicalDeviceSurfaceSupportKHR GetPhysicalDeviceSurfaceSupportKHR = inst.load("vkGetPhysicalDeviceSurfaceSupportKHR");
4530     PFN_vkCreateSwapchainKHR CreateSwapchainKHR = dev.load("vkCreateSwapchainKHR");
4531     PFN_vkGetSwapchainImagesKHR GetSwapchainImagesKHR = dev.load("vkGetSwapchainImagesKHR");
4532     PFN_vkDestroySwapchainKHR DestroySwapchainKHR = dev.load("vkDestroySwapchainKHR");
4533     ASSERT_TRUE(nullptr != GetPhysicalDeviceSurfaceSupportKHR);
4534     ASSERT_TRUE(nullptr != CreateSwapchainKHR);
4535     ASSERT_TRUE(nullptr != GetSwapchainImagesKHR);
4536     ASSERT_TRUE(nullptr != DestroySwapchainKHR);
4537 
4538     VkBool32 supported = false;
4539     ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceSurfaceSupportKHR(physical_device, 0, surface, &supported));
4540     ASSERT_EQ(supported, VK_TRUE);
4541 
4542     VkSwapchainKHR swapchain{};
4543     VkSwapchainCreateInfoKHR swap_create_info{};
4544     swap_create_info.surface = surface;
4545 
4546     ASSERT_EQ(VK_SUCCESS, CreateSwapchainKHR(dev, &swap_create_info, nullptr, &swapchain));
4547     uint32_t count = 0;
4548     ASSERT_EQ(VK_SUCCESS, GetSwapchainImagesKHR(dev, swapchain, &count, nullptr));
4549     ASSERT_GT(count, 0U);
4550     std::array<VkImage, 16> images;
4551     ASSERT_EQ(VK_SUCCESS, GetSwapchainImagesKHR(dev, swapchain, &count, images.data()));
4552     DestroySwapchainKHR(dev, swapchain, nullptr);
4553 }
4554 
add_driver_for_unloading_testing(FrameworkEnvironment & env)4555 void add_driver_for_unloading_testing(FrameworkEnvironment& env) {
4556     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2))
4557         .add_instance_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME)
4558         .setup_WSI()
4559         .add_physical_device(PhysicalDevice{}
4560                                  .add_extension("VK_KHR_swapchain")
4561                                  .add_queue_family_properties({{VK_QUEUE_GRAPHICS_BIT, 1, 0, {1, 1, 1}}, true})
4562                                  .finish());
4563 }
4564 
add_empty_driver_for_unloading_testing(FrameworkEnvironment & env)4565 void add_empty_driver_for_unloading_testing(FrameworkEnvironment& env) {
4566     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_instance_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME).setup_WSI();
4567 }
4568 
TEST(DriverUnloadingFromZeroPhysDevs,InterspersedThroughout)4569 TEST(DriverUnloadingFromZeroPhysDevs, InterspersedThroughout) {
4570     FrameworkEnvironment env{};
4571     add_empty_driver_for_unloading_testing(env);
4572     add_driver_for_unloading_testing(env);
4573     add_empty_driver_for_unloading_testing(env);
4574     add_driver_for_unloading_testing(env);
4575     add_empty_driver_for_unloading_testing(env);
4576 
4577     DebugUtilsLogger debug_log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
4578     InstWrapper inst{env.vulkan_functions};
4579     inst.create_info.setup_WSI().add_extension("VK_EXT_debug_report");
4580     FillDebugUtilsCreateDetails(inst.create_info, debug_log);
4581     inst.CheckCreate();
4582     DebugUtilsWrapper log{inst};
4583     ASSERT_EQ(VK_SUCCESS, CreateDebugUtilsMessenger(log));
4584 
4585     PFN_vkSubmitDebugUtilsMessageEXT submit_message = inst.load("vkSubmitDebugUtilsMessageEXT");
4586     ASSERT_TRUE(submit_message != nullptr);
4587 
4588     VkSurfaceKHR pre_surface{};
4589     ASSERT_EQ(VK_SUCCESS, create_surface(inst, pre_surface));
4590     WrappedHandle<VkSurfaceKHR, VkInstance, PFN_vkDestroySurfaceKHR> pre_enum_phys_devs_surface{
4591         pre_surface, inst.inst, env.vulkan_functions.vkDestroySurfaceKHR};
4592 
4593     VkDebugReportCallbackEXT debug_callback{};
4594     VkDebugReportCallbackCreateInfoEXT debug_report_create_info{};
4595     ASSERT_EQ(VK_SUCCESS, create_debug_callback(inst, debug_report_create_info, debug_callback));
4596     WrappedHandle<VkDebugReportCallbackEXT, VkInstance, PFN_vkDestroyDebugReportCallbackEXT>
4597         pre_enum_phys_devs_debug_report_callback{debug_callback, inst.inst, env.vulkan_functions.vkDestroyDebugReportCallbackEXT};
4598 
4599     auto phys_devs = inst.GetPhysDevs();
4600     std::vector<WrappedHandle<VkDebugUtilsMessengerEXT, VkInstance, PFN_vkDestroyDebugUtilsMessengerEXT>> messengers;
4601     std::vector<WrappedHandle<VkSurfaceKHR, VkInstance, PFN_vkDestroySurfaceKHR>> surfaces;
4602     for (uint32_t i = 0; i < 35; i++) {
4603         VkDebugUtilsMessengerEXT messenger;
4604         ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateDebugUtilsMessengerEXT(inst.inst, log.get(), nullptr, &messenger));
4605         messengers.emplace_back(messenger, inst.inst, env.vulkan_functions.vkDestroyDebugUtilsMessengerEXT);
4606 
4607         VkSurfaceKHR surface{};
4608         ASSERT_EQ(VK_SUCCESS, create_surface(inst, surface));
4609         surfaces.emplace_back(surface, inst.inst, env.vulkan_functions.vkDestroySurfaceKHR);
4610     }
4611     for (const auto& phys_dev : phys_devs) {
4612         DeviceWrapper dev{inst};
4613         dev.create_info.add_extension("VK_KHR_swapchain");
4614         dev.CheckCreate(phys_dev);
4615         for (const auto& surface : surfaces) {
4616             try_create_swapchain(inst, phys_dev, dev, surface.handle);
4617         }
4618     }
4619 }
4620 
TEST(DriverUnloadingFromZeroPhysDevs,InMiddleOfList)4621 TEST(DriverUnloadingFromZeroPhysDevs, InMiddleOfList) {
4622     FrameworkEnvironment env{};
4623     add_driver_for_unloading_testing(env);
4624     add_empty_driver_for_unloading_testing(env);
4625     add_empty_driver_for_unloading_testing(env);
4626     add_empty_driver_for_unloading_testing(env);
4627     add_driver_for_unloading_testing(env);
4628 
4629     InstWrapper inst{env.vulkan_functions};
4630     inst.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
4631     inst.create_info.setup_WSI().add_extension("VK_EXT_debug_report");
4632     inst.CheckCreate();
4633     DebugUtilsWrapper log{inst};
4634     ASSERT_EQ(VK_SUCCESS, CreateDebugUtilsMessenger(log));
4635 
4636     VkSurfaceKHR pre_surface{};
4637     ASSERT_EQ(VK_SUCCESS, create_surface(inst, pre_surface));
4638     WrappedHandle<VkSurfaceKHR, VkInstance, PFN_vkDestroySurfaceKHR> pre_enum_phys_devs_surface{
4639         pre_surface, inst.inst, env.vulkan_functions.vkDestroySurfaceKHR};
4640 
4641     VkDebugReportCallbackEXT debug_callback{};
4642     VkDebugReportCallbackCreateInfoEXT debug_report_create_info{};
4643     ASSERT_EQ(VK_SUCCESS, create_debug_callback(inst, debug_report_create_info, debug_callback));
4644     WrappedHandle<VkDebugReportCallbackEXT, VkInstance, PFN_vkDestroyDebugReportCallbackEXT>
4645         pre_enum_phys_devs_debug_report_callback{debug_callback, inst.inst, env.vulkan_functions.vkDestroyDebugReportCallbackEXT};
4646 
4647     auto phys_devs = inst.GetPhysDevs();
4648     std::vector<WrappedHandle<VkDebugUtilsMessengerEXT, VkInstance, PFN_vkDestroyDebugUtilsMessengerEXT>> messengers;
4649     std::vector<WrappedHandle<VkSurfaceKHR, VkInstance, PFN_vkDestroySurfaceKHR>> surfaces;
4650     for (uint32_t i = 0; i < 35; i++) {
4651         VkDebugUtilsMessengerEXT messenger;
4652         ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateDebugUtilsMessengerEXT(inst.inst, log.get(), nullptr, &messenger));
4653         messengers.emplace_back(messenger, inst.inst, env.vulkan_functions.vkDestroyDebugUtilsMessengerEXT);
4654 
4655         VkSurfaceKHR surface{};
4656         ASSERT_EQ(VK_SUCCESS, create_surface(inst, surface));
4657         surfaces.emplace_back(surface, inst.inst, env.vulkan_functions.vkDestroySurfaceKHR);
4658     }
4659     for (const auto& phys_dev : phys_devs) {
4660         DeviceWrapper dev{inst};
4661         dev.create_info.add_extension("VK_KHR_swapchain");
4662         dev.CheckCreate(phys_dev);
4663         for (const auto& surface : surfaces) {
4664             try_create_swapchain(inst, phys_dev, dev, surface.handle);
4665         }
4666     }
4667 }
4668 
TEST(DriverUnloadingFromZeroPhysDevs,AtFrontAndBack)4669 TEST(DriverUnloadingFromZeroPhysDevs, AtFrontAndBack) {
4670     FrameworkEnvironment env{};
4671     add_empty_driver_for_unloading_testing(env);
4672     add_empty_driver_for_unloading_testing(env);
4673     add_driver_for_unloading_testing(env);
4674     add_driver_for_unloading_testing(env);
4675     add_empty_driver_for_unloading_testing(env);
4676     add_empty_driver_for_unloading_testing(env);
4677 
4678     DebugUtilsLogger debug_log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
4679     InstWrapper inst{env.vulkan_functions};
4680     inst.create_info.setup_WSI().add_extension("VK_EXT_debug_report");
4681     FillDebugUtilsCreateDetails(inst.create_info, debug_log);
4682     inst.CheckCreate();
4683 
4684     DebugUtilsWrapper log{inst};
4685     ASSERT_EQ(VK_SUCCESS, CreateDebugUtilsMessenger(log));
4686 
4687     VkSurfaceKHR pre_surface{};
4688     ASSERT_EQ(VK_SUCCESS, create_surface(inst, pre_surface));
4689     WrappedHandle<VkSurfaceKHR, VkInstance, PFN_vkDestroySurfaceKHR> pre_enum_phys_devs_surface{
4690         pre_surface, inst.inst, env.vulkan_functions.vkDestroySurfaceKHR};
4691 
4692     VkDebugReportCallbackEXT debug_callback{};
4693     VkDebugReportCallbackCreateInfoEXT debug_report_create_info{};
4694     ASSERT_EQ(VK_SUCCESS, create_debug_callback(inst, debug_report_create_info, debug_callback));
4695     WrappedHandle<VkDebugReportCallbackEXT, VkInstance, PFN_vkDestroyDebugReportCallbackEXT>
4696         pre_enum_phys_devs_debug_report_callback{debug_callback, inst.inst, env.vulkan_functions.vkDestroyDebugReportCallbackEXT};
4697 
4698     auto phys_devs = inst.GetPhysDevs();
4699     std::vector<WrappedHandle<VkDebugUtilsMessengerEXT, VkInstance, PFN_vkDestroyDebugUtilsMessengerEXT>> messengers;
4700     std::vector<WrappedHandle<VkSurfaceKHR, VkInstance, PFN_vkDestroySurfaceKHR>> surfaces;
4701     for (uint32_t i = 0; i < 35; i++) {
4702         VkDebugUtilsMessengerEXT messenger;
4703         ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateDebugUtilsMessengerEXT(inst.inst, log.get(), nullptr, &messenger));
4704         messengers.emplace_back(messenger, inst.inst, env.vulkan_functions.vkDestroyDebugUtilsMessengerEXT);
4705 
4706         VkSurfaceKHR surface{};
4707         ASSERT_EQ(VK_SUCCESS, create_surface(inst, surface));
4708         surfaces.emplace_back(surface, inst.inst, env.vulkan_functions.vkDestroySurfaceKHR);
4709     }
4710     for (const auto& phys_dev : phys_devs) {
4711         DeviceWrapper dev{inst};
4712         dev.create_info.add_extension("VK_KHR_swapchain");
4713         dev.CheckCreate(phys_dev);
4714 
4715         for (const auto& surface : surfaces) {
4716             try_create_swapchain(inst, phys_dev, dev, surface.handle);
4717         }
4718     }
4719 }
4720 
TEST(DriverUnloadingFromZeroPhysDevs,MultipleEnumerateCalls)4721 TEST(DriverUnloadingFromZeroPhysDevs, MultipleEnumerateCalls) {
4722     FrameworkEnvironment env{};
4723     add_empty_driver_for_unloading_testing(env);
4724     add_empty_driver_for_unloading_testing(env);
4725     add_driver_for_unloading_testing(env);
4726     add_driver_for_unloading_testing(env);
4727     add_empty_driver_for_unloading_testing(env);
4728     add_empty_driver_for_unloading_testing(env);
4729 
4730     uint32_t extension_count = 0;
4731     ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, 0));
4732     ASSERT_EQ(extension_count, 6U);  // default extensions + surface extensions
4733     std::array<VkExtensionProperties, 6> extensions;
4734     ASSERT_EQ(VK_SUCCESS,
4735               env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extensions.data()));
4736 
4737     {
4738         InstWrapper inst{env.vulkan_functions};
4739         inst.CheckCreate();
4740         auto phys_devs1 = inst.GetPhysDevs();
4741         auto phys_devs2 = inst.GetPhysDevs();
4742     }
4743     {
4744         InstWrapper inst{env.vulkan_functions};
4745         inst.CheckCreate();
4746         auto phys_devs1 = inst.GetPhysDevs();
4747         auto phys_devs2 = inst.GetPhysDevs();
4748     }
4749 }
TEST(DriverUnloadingFromZeroPhysDevs,NoPhysicalDevices)4750 TEST(DriverUnloadingFromZeroPhysDevs, NoPhysicalDevices) {
4751     FrameworkEnvironment env{};
4752     add_empty_driver_for_unloading_testing(env);
4753     add_empty_driver_for_unloading_testing(env);
4754     add_empty_driver_for_unloading_testing(env);
4755     add_empty_driver_for_unloading_testing(env);
4756 
4757     DebugUtilsLogger debug_log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
4758     InstWrapper inst{env.vulkan_functions};
4759     inst.create_info.setup_WSI().add_extension("VK_EXT_debug_report");
4760     FillDebugUtilsCreateDetails(inst.create_info, debug_log);
4761     inst.CheckCreate();
4762     DebugUtilsWrapper log{inst};
4763     ASSERT_EQ(VK_SUCCESS, CreateDebugUtilsMessenger(log));
4764 
4765     VkSurfaceKHR pre_surface{};
4766     ASSERT_EQ(VK_SUCCESS, create_surface(inst, pre_surface));
4767     WrappedHandle<VkSurfaceKHR, VkInstance, PFN_vkDestroySurfaceKHR> pre_enum_phys_devs_surface{
4768         pre_surface, inst.inst, env.vulkan_functions.vkDestroySurfaceKHR};
4769 
4770     VkDebugReportCallbackEXT debug_callback{};
4771     VkDebugReportCallbackCreateInfoEXT debug_report_create_info{};
4772     ASSERT_EQ(VK_SUCCESS, create_debug_callback(inst, debug_report_create_info, debug_callback));
4773     WrappedHandle<VkDebugReportCallbackEXT, VkInstance, PFN_vkDestroyDebugReportCallbackEXT>
4774         pre_enum_phys_devs_debug_report_callback{debug_callback, inst.inst, env.vulkan_functions.vkDestroyDebugReportCallbackEXT};
4775 
4776     // No physical devices == VK_ERROR_INITIALIZATION_FAILED
4777     inst.GetPhysDevs(VK_ERROR_INITIALIZATION_FAILED);
4778 
4779     std::vector<WrappedHandle<VkDebugUtilsMessengerEXT, VkInstance, PFN_vkDestroyDebugUtilsMessengerEXT>> messengers;
4780     std::vector<WrappedHandle<VkSurfaceKHR, VkInstance, PFN_vkDestroySurfaceKHR>> surfaces;
4781     for (uint32_t i = 0; i < 35; i++) {
4782         VkDebugUtilsMessengerEXT messenger;
4783         ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateDebugUtilsMessengerEXT(inst.inst, log.get(), nullptr, &messenger));
4784         messengers.emplace_back(messenger, inst.inst, env.vulkan_functions.vkDestroyDebugUtilsMessengerEXT);
4785 
4786         VkSurfaceKHR surface{};
4787         ASSERT_EQ(VK_SUCCESS, create_surface(inst, surface));
4788         surfaces.emplace_back(surface, inst.inst, env.vulkan_functions.vkDestroySurfaceKHR);
4789     }
4790 }
4791 
TEST(DriverUnloadingFromZeroPhysDevs,HandleRecreation)4792 TEST(DriverUnloadingFromZeroPhysDevs, HandleRecreation) {
4793     FrameworkEnvironment env{};
4794     add_empty_driver_for_unloading_testing(env);
4795     add_driver_for_unloading_testing(env);
4796     add_empty_driver_for_unloading_testing(env);
4797     add_driver_for_unloading_testing(env);
4798     add_empty_driver_for_unloading_testing(env);
4799 
4800     DebugUtilsLogger debug_log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
4801     InstWrapper inst{env.vulkan_functions};
4802     inst.create_info.setup_WSI().add_extension("VK_EXT_debug_report");
4803     FillDebugUtilsCreateDetails(inst.create_info, debug_log);
4804     inst.CheckCreate();
4805     DebugUtilsWrapper log{inst};
4806     ASSERT_EQ(VK_SUCCESS, CreateDebugUtilsMessenger(log));
4807 
4808     PFN_vkSubmitDebugUtilsMessageEXT submit_message = inst.load("vkSubmitDebugUtilsMessageEXT");
4809     ASSERT_TRUE(submit_message != nullptr);
4810 
4811     VkSurfaceKHR pre_surface{};
4812     ASSERT_EQ(VK_SUCCESS, create_surface(inst, pre_surface));
4813     WrappedHandle<VkSurfaceKHR, VkInstance, PFN_vkDestroySurfaceKHR> pre_enum_phys_devs_surface{
4814         pre_surface, inst.inst, env.vulkan_functions.vkDestroySurfaceKHR};
4815 
4816     VkDebugReportCallbackEXT debug_callback{};
4817     VkDebugReportCallbackCreateInfoEXT debug_report_create_info{};
4818     ASSERT_EQ(VK_SUCCESS, create_debug_callback(inst, debug_report_create_info, debug_callback));
4819     WrappedHandle<VkDebugReportCallbackEXT, VkInstance, PFN_vkDestroyDebugReportCallbackEXT>
4820         pre_enum_phys_devs_debug_report_callback{debug_callback, inst.inst, env.vulkan_functions.vkDestroyDebugReportCallbackEXT};
4821 
4822     auto phys_devs = inst.GetPhysDevs();
4823     std::vector<WrappedHandle<VkDebugUtilsMessengerEXT, VkInstance, PFN_vkDestroyDebugUtilsMessengerEXT>> messengers;
4824     std::vector<WrappedHandle<VkSurfaceKHR, VkInstance, PFN_vkDestroySurfaceKHR>> surfaces;
4825     for (uint32_t i = 0; i < 35; i++) {
4826         VkDebugUtilsMessengerEXT messenger;
4827         ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateDebugUtilsMessengerEXT(inst.inst, log.get(), nullptr, &messenger));
4828         messengers.emplace_back(messenger, inst.inst, env.vulkan_functions.vkDestroyDebugUtilsMessengerEXT);
4829 
4830         VkSurfaceKHR surface{};
4831         ASSERT_EQ(VK_SUCCESS, create_surface(inst, surface));
4832         surfaces.emplace_back(surface, inst.inst, env.vulkan_functions.vkDestroySurfaceKHR);
4833     }
4834     // Remove some elements arbitrarily - remove 15 of each
4835     // Do it backwards so the indexes are 'corect'
4836     for (uint32_t i = 31; i > 2; i -= 2) {
4837         messengers.erase(messengers.begin() + i);
4838         surfaces.erase(surfaces.begin() + i);
4839     }
4840     // Add in another 100
4841     for (uint32_t i = 0; i < 100; i++) {
4842         VkDebugUtilsMessengerEXT messenger;
4843         ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateDebugUtilsMessengerEXT(inst.inst, log.get(), nullptr, &messenger));
4844         messengers.emplace_back(messenger, inst.inst, env.vulkan_functions.vkDestroyDebugUtilsMessengerEXT);
4845 
4846         VkSurfaceKHR surface{};
4847         ASSERT_EQ(VK_SUCCESS, create_surface(inst, surface));
4848         surfaces.emplace_back(surface, inst.inst, env.vulkan_functions.vkDestroySurfaceKHR);
4849     }
4850     for (const auto& phys_dev : phys_devs) {
4851         DeviceWrapper dev{inst};
4852         dev.create_info.add_extension("VK_KHR_swapchain");
4853         dev.CheckCreate(phys_dev);
4854         for (const auto& surface : surfaces) {
4855             try_create_swapchain(inst, phys_dev, dev, surface.handle);
4856         }
4857     }
4858     VkDebugUtilsMessengerCallbackDataEXT data{};
4859     data.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT;
4860     data.pMessage = "I'm a test message!";
4861     data.messageIdNumber = 1;
4862     submit_message(inst.inst, VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, &data);
4863 
4864     ASSERT_EQ(120U + 1U, log.count(data.pMessage));
4865 }
4866