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