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