1 /*
2 * Copyright (c) 2021-2022 The Khronos Group Inc.
3 * Copyright (c) 2021-2022 Valve Corporation
4 * Copyright (c) 2021-2022 LunarG, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and/or associated documentation files (the "Materials"), to
8 * deal in the Materials without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Materials, and to permit persons to whom the Materials are
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice(s) and this permission notice shall be included in
14 * all copies or substantial portions of the Materials.
15 *
16 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 *
20 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
23 * USE OR OTHER DEALINGS IN THE MATERIALS.
24 *
25 * Author: Charles Giessen <charles@lunarg.com>
26 * Author: Mark Young <marky@lunarg.com>
27 */
28
29 #include "test_environment.h"
30
31 // These tests are all instance extension tests that touch physical devices. This was
32 // before the idea that physical device extensions were more appropriately found in the
33 // list of device extensions. Because of that, all these tests need to support devices
34 // that don't support the extension and have a fallback path in the loader that needs
35 // validation.
36
37 // Fill in random but valid data into the device properties struct for the current physical device
FillInRandomICDInfo(uint32_t& vendor_id, uint32_t& driver_vers)38 void FillInRandomICDInfo(uint32_t& vendor_id, uint32_t& driver_vers) {
39 vendor_id = VK_MAKE_API_VERSION(0, rand() % 64, rand() % 255, rand() % 255);
40 driver_vers = VK_MAKE_API_VERSION(0, rand() % 64, rand() % 255, rand() % 255);
41 }
42
43 // Fill in random but valid data into the device properties struct for the current physical device
FillInRandomDeviceProps(VkPhysicalDeviceProperties& props, uint32_t api_vers, uint32_t vendor, uint32_t driver_vers)44 void FillInRandomDeviceProps(VkPhysicalDeviceProperties& props, uint32_t api_vers, uint32_t vendor, uint32_t driver_vers) {
45 props.apiVersion = api_vers;
46 props.driverVersion = driver_vers;
47 props.vendorID = vendor;
48 props.deviceID = (static_cast<uint32_t>(rand()) >> 4) + (static_cast<uint32_t>(rand()) << 2);
49 props.deviceType = static_cast<VkPhysicalDeviceType>(rand() % 5);
50 for (uint8_t idx = 0; idx < VK_UUID_SIZE; ++idx) {
51 props.pipelineCacheUUID[idx] = static_cast<uint8_t>(rand() % 255);
52 }
53 }
54
55 //
56 // VK_KHR_get_physical_device_properties2
57 //
58
59 // Test vkGetPhysicalDeviceProperties2KHR where nothing supports it.
TEST(LoaderInstPhysDevExts, PhysDevProps2KHRNoSupport)60 TEST(LoaderInstPhysDevExts, PhysDevProps2KHRNoSupport) {
61 FrameworkEnvironment env{};
62 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
63 env.get_test_icd(0).physical_devices.push_back({});
64
65 InstWrapper instance(env.vulkan_functions);
66 instance.CheckCreate();
67
68 PFN_vkGetPhysicalDeviceProperties2KHR GetPhysDevProps2 = instance.load("vkGetPhysicalDeviceProperties2KHR");
69 ASSERT_EQ(GetPhysDevProps2, nullptr);
70 }
71
72 // Test vkGetPhysicalDeviceProperties2KHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevProps2KHRNoICDSupport)73 TEST(LoaderInstPhysDevExts, PhysDevProps2KHRNoICDSupport) {
74 FrameworkEnvironment env{};
75 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
76 env.get_test_icd(0).physical_devices.push_back({});
77
78 InstWrapper instance(env.vulkan_functions);
79 instance.create_info.add_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
80 instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
81
82 PFN_vkGetPhysicalDeviceProperties2KHR GetPhysDevProps2 = instance.load("vkGetPhysicalDeviceProperties2KHR");
83 ASSERT_EQ(GetPhysDevProps2, nullptr);
84 }
85
86 // Test vkGetPhysicalDeviceProperties2KHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, PhysDevProps2KHRInstanceAndICDSupport)87 TEST(LoaderInstPhysDevExts, PhysDevProps2KHRInstanceAndICDSupport) {
88 FrameworkEnvironment env{};
89 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
90 env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
91 env.get_test_icd(0).physical_devices.push_back({});
92 FillInRandomDeviceProps(env.get_test_icd(0).physical_devices.back().properties, VK_API_VERSION_1_0, 5, 123);
93
94 InstWrapper instance(env.vulkan_functions);
95 instance.create_info.add_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
96 instance.CheckCreate();
97
98 PFN_vkGetPhysicalDeviceProperties2KHR GetPhysDevProps2 = instance.load("vkGetPhysicalDeviceProperties2KHR");
99 ASSERT_NE(GetPhysDevProps2, nullptr);
100
101 uint32_t driver_count = 1;
102 VkPhysicalDevice physical_device;
103 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
104 ASSERT_EQ(driver_count, 1U);
105
106 VkPhysicalDeviceProperties props{};
107 instance->vkGetPhysicalDeviceProperties(physical_device, &props);
108 VkPhysicalDeviceProperties2KHR props2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR};
109 GetPhysDevProps2(physical_device, &props2);
110
111 // Both properties should match
112 ASSERT_EQ(props.apiVersion, props2.properties.apiVersion);
113 ASSERT_EQ(props.driverVersion, props2.properties.driverVersion);
114 ASSERT_EQ(props.vendorID, props2.properties.vendorID);
115 ASSERT_EQ(props.deviceID, props2.properties.deviceID);
116 ASSERT_EQ(props.deviceType, props2.properties.deviceType);
117 ASSERT_EQ(0, memcmp(props.pipelineCacheUUID, props2.properties.pipelineCacheUUID, VK_UUID_SIZE));
118 }
119
120 // Test vkGetPhysicalDeviceProperties2 where instance supports, an ICD, and a device under that ICD
121 // also support, so everything should work and return properly.
122 // Also check if the application didn't enable 1.1 and when a layer 'upgrades' the api version to 1.1
TEST(LoaderInstPhysDevExts, PhysDevProps2Simple)123 TEST(LoaderInstPhysDevExts, PhysDevProps2Simple) {
124 FrameworkEnvironment env{};
125 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, VK_API_VERSION_1_1));
126 env.get_test_icd(0).icd_api_version = VK_API_VERSION_1_1;
127 env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
128 env.get_test_icd(0).physical_devices.push_back({});
129 env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
130 FillInRandomDeviceProps(env.get_test_icd(0).physical_devices.back().properties, VK_API_VERSION_1_1, 5, 123);
131 {
132 InstWrapper instance(env.vulkan_functions);
133 instance.create_info.set_api_version(VK_API_VERSION_1_1);
134 instance.CheckCreate();
135
136 PFN_vkGetPhysicalDeviceProperties2 GetPhysDevProps2 = instance.load("vkGetPhysicalDeviceProperties2");
137 ASSERT_NE(GetPhysDevProps2, nullptr);
138
139 uint32_t driver_count = 1;
140 VkPhysicalDevice physical_device;
141 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
142 ASSERT_EQ(driver_count, 1U);
143
144 VkPhysicalDeviceProperties props{};
145 instance->vkGetPhysicalDeviceProperties(physical_device, &props);
146 VkPhysicalDeviceProperties2KHR props2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR};
147 GetPhysDevProps2(physical_device, &props2);
148
149 // Both properties should match
150 ASSERT_EQ(props.apiVersion, props2.properties.apiVersion);
151 ASSERT_EQ(props.driverVersion, props2.properties.driverVersion);
152 ASSERT_EQ(props.vendorID, props2.properties.vendorID);
153 ASSERT_EQ(props.deviceID, props2.properties.deviceID);
154 ASSERT_EQ(props.deviceType, props2.properties.deviceType);
155 ASSERT_EQ(0, memcmp(props.pipelineCacheUUID, props2.properties.pipelineCacheUUID, VK_UUID_SIZE));
156 }
157
158 { // Do the same logic but have the application forget to use 1.1 and doesn't enable the extension - should emulate the call
159 InstWrapper instance(env.vulkan_functions);
160 instance.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
161 instance.CheckCreate();
162 DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
163 CreateDebugUtilsMessenger(log);
164
165 PFN_vkGetPhysicalDeviceProperties2 GetPhysDevProps2 = instance.load("vkGetPhysicalDeviceProperties2");
166 ASSERT_NE(GetPhysDevProps2, nullptr);
167
168 uint32_t driver_count = 1;
169 VkPhysicalDevice physical_device;
170 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
171 ASSERT_EQ(driver_count, 1U);
172
173 VkPhysicalDeviceProperties props{};
174 instance->vkGetPhysicalDeviceProperties(physical_device, &props);
175 VkPhysicalDeviceProperties2KHR props2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR};
176 GetPhysDevProps2(physical_device, &props2);
177
178 // Both properties should match
179 ASSERT_EQ(props.apiVersion, props2.properties.apiVersion);
180 ASSERT_EQ(props.driverVersion, props2.properties.driverVersion);
181 ASSERT_EQ(props.vendorID, props2.properties.vendorID);
182 ASSERT_EQ(props.deviceID, props2.properties.deviceID);
183 ASSERT_EQ(props.deviceType, props2.properties.deviceType);
184 ASSERT_EQ(0, memcmp(props.pipelineCacheUUID, props2.properties.pipelineCacheUUID, VK_UUID_SIZE));
185 ASSERT_TRUE(log.find("Emulating call in ICD"));
186 }
187 env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
188 .set_name("modify_api_version_layer")
189 .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
190 .set_disable_environment("DisableEnvVar")),
191 "modify_api_version_layer.json");
192 env.get_test_layer().set_alter_api_version(VK_API_VERSION_1_1);
193 { // Now do the same as above but with a layer that updates the version to 1.1
194 InstWrapper instance(env.vulkan_functions);
195 instance.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
196 instance.CheckCreate();
197 DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
198 CreateDebugUtilsMessenger(log);
199
200 PFN_vkGetPhysicalDeviceProperties2 GetPhysDevProps2 = instance.load("vkGetPhysicalDeviceProperties2");
201 ASSERT_NE(GetPhysDevProps2, nullptr);
202
203 uint32_t driver_count = 1;
204 VkPhysicalDevice physical_device;
205 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
206 ASSERT_EQ(driver_count, 1U);
207
208 VkPhysicalDeviceProperties props{};
209 instance->vkGetPhysicalDeviceProperties(physical_device, &props);
210 VkPhysicalDeviceProperties2KHR props2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR};
211 GetPhysDevProps2(physical_device, &props2);
212
213 // Both properties should match
214 ASSERT_EQ(props.apiVersion, props2.properties.apiVersion);
215 ASSERT_EQ(props.driverVersion, props2.properties.driverVersion);
216 ASSERT_EQ(props.vendorID, props2.properties.vendorID);
217 ASSERT_EQ(props.deviceID, props2.properties.deviceID);
218 ASSERT_EQ(props.deviceType, props2.properties.deviceType);
219 ASSERT_EQ(0, memcmp(props.pipelineCacheUUID, props2.properties.pipelineCacheUUID, VK_UUID_SIZE));
220 ASSERT_FALSE(log.find("Emulating call in ICD"));
221 }
222 }
223
224 // Test vkGetPhysicalDeviceProperties2 and vkGetPhysicalDeviceProperties2KHR where ICD is 1.0 and supports
225 // extension but the instance supports 1.1 and the extension
TEST(LoaderInstPhysDevExts, PhysDevProps2KHRInstanceSupports11)226 TEST(LoaderInstPhysDevExts, PhysDevProps2KHRInstanceSupports11) {
227 FrameworkEnvironment env{};
228 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, VK_API_VERSION_1_0));
229 env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
230 env.get_test_icd(0).physical_devices.push_back({});
231 env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
232 FillInRandomDeviceProps(env.get_test_icd(0).physical_devices.back().properties, VK_API_VERSION_1_0, 5, 123);
233
234 InstWrapper instance(env.vulkan_functions);
235 instance.create_info.set_api_version(VK_API_VERSION_1_1);
236 instance.create_info.add_extensions(
237 {VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_EXTENSION_NAME});
238 instance.CheckCreate();
239 DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
240 CreateDebugUtilsMessenger(log);
241
242 PFN_vkGetPhysicalDeviceProperties2 GetPhysDevProps2 = instance.load("vkGetPhysicalDeviceProperties2");
243 ASSERT_NE(GetPhysDevProps2, nullptr);
244
245 PFN_vkGetPhysicalDeviceProperties2 GetPhysDevProps2KHR = instance.load("vkGetPhysicalDeviceProperties2KHR");
246 ASSERT_NE(GetPhysDevProps2KHR, nullptr);
247
248 uint32_t driver_count = 1;
249 VkPhysicalDevice physical_device;
250 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
251 ASSERT_EQ(driver_count, 1U);
252
253 VkPhysicalDeviceProperties props{};
254 instance->vkGetPhysicalDeviceProperties(physical_device, &props);
255 VkPhysicalDeviceProperties2 props2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2};
256 GetPhysDevProps2(physical_device, &props2);
257
258 // Both VkPhysicalDeviceProperties2 properties should match
259 ASSERT_EQ(props.apiVersion, props2.properties.apiVersion);
260 ASSERT_EQ(props.driverVersion, props2.properties.driverVersion);
261 ASSERT_EQ(props.vendorID, props2.properties.vendorID);
262 ASSERT_EQ(props.deviceID, props2.properties.deviceID);
263 ASSERT_EQ(props.deviceType, props2.properties.deviceType);
264 ASSERT_EQ(0, memcmp(props.pipelineCacheUUID, props2.properties.pipelineCacheUUID, VK_UUID_SIZE));
265
266 VkPhysicalDeviceProperties2KHR props2KHR{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR};
267 GetPhysDevProps2(physical_device, &props2KHR);
268
269 // Both VkPhysicalDeviceProperties2KHR properties should match
270 ASSERT_EQ(props.apiVersion, props2KHR.properties.apiVersion);
271 ASSERT_EQ(props.driverVersion, props2KHR.properties.driverVersion);
272 ASSERT_EQ(props.vendorID, props2KHR.properties.vendorID);
273 ASSERT_EQ(props.deviceID, props2KHR.properties.deviceID);
274 ASSERT_EQ(props.deviceType, props2KHR.properties.deviceType);
275 ASSERT_EQ(0, memcmp(props.pipelineCacheUUID, props2KHR.properties.pipelineCacheUUID, VK_UUID_SIZE));
276
277 ASSERT_FALSE(log.find("Emulating call in ICD"));
278 }
279
280 // Test vkGetPhysicalDeviceProperties2 where instance supports it with some ICDs that both support
281 // and don't support it:
282 // ICD 0 supports
283 // Physical device 0 does not
284 // Physical device 1 does
285 // Physical device 2 does not
286 // ICD 1 doesn't support
287 // Physical device 3 does not
288 // ICD 2 supports
289 // Physical device 4 does not
290 // Physical device 5 does not
291 // ICD 3 supports
292 // Physical device 6 does
TEST(LoaderInstPhysDevExts, PhysDevProps2Mixed)293 TEST(LoaderInstPhysDevExts, PhysDevProps2Mixed) {
294 FrameworkEnvironment env{};
295 const uint32_t max_icd_count = 4;
296 const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
297 const uint32_t max_phys_devs = 7;
298
299 for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
300 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, icd != 1 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0));
301 auto& cur_icd = env.get_test_icd(icd);
302
303 // ICD 1 should not have 1.1
304 if (icd != 1) {
305 cur_icd.icd_api_version = VK_API_VERSION_1_1;
306 cur_icd.add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
307 }
308
309 uint32_t rand_vendor_id;
310 uint32_t rand_driver_vers;
311 FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
312
313 for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
314 uint32_t device_version = VK_API_VERSION_1_0;
315 cur_icd.physical_devices.push_back({});
316 auto& cur_dev = cur_icd.physical_devices.back();
317
318 // 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
319 if ((icd == 0 && dev == 1) || icd == 3) {
320 cur_dev.extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
321 device_version = VK_API_VERSION_1_1;
322 }
323 FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
324 }
325 }
326
327 InstWrapper instance(env.vulkan_functions);
328 instance.create_info.set_api_version(VK_API_VERSION_1_1);
329 instance.CheckCreate();
330
331 PFN_vkGetPhysicalDeviceProperties2 GetPhysDevProps2 = instance.load("vkGetPhysicalDeviceProperties2");
332 ASSERT_NE(GetPhysDevProps2, nullptr);
333
334 uint32_t device_count = max_phys_devs;
335 std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
336 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
337 ASSERT_EQ(device_count, max_phys_devs);
338
339 for (uint32_t dev = 0; dev < device_count; ++dev) {
340 VkPhysicalDeviceProperties props{};
341 instance->vkGetPhysicalDeviceProperties(physical_devices[dev], &props);
342 VkPhysicalDeviceProperties2KHR props2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2};
343 GetPhysDevProps2(physical_devices[dev], &props2);
344
345 // Both properties should match
346 ASSERT_EQ(props.apiVersion, props2.properties.apiVersion);
347 ASSERT_EQ(props.driverVersion, props2.properties.driverVersion);
348 ASSERT_EQ(props.vendorID, props2.properties.vendorID);
349 ASSERT_EQ(props.deviceID, props2.properties.deviceID);
350 ASSERT_EQ(props.deviceType, props2.properties.deviceType);
351 ASSERT_EQ(0, memcmp(props.pipelineCacheUUID, props2.properties.pipelineCacheUUID, VK_UUID_SIZE));
352 }
353 }
354
355 // Fill in random but valid data into the features struct for the current physical device
FillInRandomFeatures(VkPhysicalDeviceFeatures& feats)356 void FillInRandomFeatures(VkPhysicalDeviceFeatures& feats) {
357 feats.robustBufferAccess = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
358 feats.fullDrawIndexUint32 = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
359 feats.imageCubeArray = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
360 feats.independentBlend = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
361 feats.geometryShader = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
362 feats.tessellationShader = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
363 feats.sampleRateShading = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
364 feats.dualSrcBlend = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
365 feats.logicOp = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
366 feats.multiDrawIndirect = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
367 feats.drawIndirectFirstInstance = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
368 feats.depthClamp = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
369 feats.depthBiasClamp = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
370 feats.fillModeNonSolid = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
371 feats.depthBounds = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
372 feats.wideLines = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
373 feats.largePoints = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
374 feats.alphaToOne = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
375 feats.multiViewport = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
376 feats.samplerAnisotropy = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
377 feats.textureCompressionETC2 = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
378 feats.textureCompressionASTC_LDR = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
379 feats.textureCompressionBC = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
380 feats.occlusionQueryPrecise = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
381 feats.pipelineStatisticsQuery = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
382 feats.vertexPipelineStoresAndAtomics = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
383 feats.fragmentStoresAndAtomics = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
384 feats.shaderTessellationAndGeometryPointSize = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
385 feats.shaderImageGatherExtended = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
386 feats.shaderStorageImageExtendedFormats = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
387 feats.shaderStorageImageMultisample = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
388 feats.shaderStorageImageReadWithoutFormat = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
389 feats.shaderStorageImageWriteWithoutFormat = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
390 feats.shaderUniformBufferArrayDynamicIndexing = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
391 feats.shaderSampledImageArrayDynamicIndexing = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
392 feats.shaderStorageBufferArrayDynamicIndexing = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
393 feats.shaderStorageImageArrayDynamicIndexing = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
394 feats.shaderClipDistance = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
395 feats.shaderCullDistance = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
396 feats.shaderFloat64 = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
397 feats.shaderInt64 = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
398 feats.shaderInt16 = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
399 feats.shaderResourceResidency = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
400 feats.shaderResourceMinLod = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
401 feats.sparseBinding = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
402 feats.sparseResidencyBuffer = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
403 feats.sparseResidencyImage2D = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
404 feats.sparseResidencyImage3D = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
405 feats.sparseResidency2Samples = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
406 feats.sparseResidency4Samples = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
407 feats.sparseResidency8Samples = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
408 feats.sparseResidency16Samples = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
409 feats.sparseResidencyAliased = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
410 feats.variableMultisampleRate = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
411 feats.inheritedQueries = (rand() % 2) == 0 ? VK_FALSE : VK_TRUE;
412 }
413
414 // Compare the contents of the feature structs
CompareFeatures(const VkPhysicalDeviceFeatures& feats1, const VkPhysicalDeviceFeatures2& feats2)415 bool CompareFeatures(const VkPhysicalDeviceFeatures& feats1, const VkPhysicalDeviceFeatures2& feats2) {
416 return feats1.robustBufferAccess == feats2.features.robustBufferAccess &&
417 feats1.fullDrawIndexUint32 == feats2.features.fullDrawIndexUint32 &&
418 feats1.imageCubeArray == feats2.features.imageCubeArray && feats1.independentBlend == feats2.features.independentBlend &&
419 feats1.geometryShader == feats2.features.geometryShader &&
420 feats1.tessellationShader == feats2.features.tessellationShader &&
421 feats1.sampleRateShading == feats2.features.sampleRateShading && feats1.dualSrcBlend == feats2.features.dualSrcBlend &&
422 feats1.logicOp == feats2.features.logicOp && feats1.multiDrawIndirect == feats2.features.multiDrawIndirect &&
423 feats1.drawIndirectFirstInstance == feats2.features.drawIndirectFirstInstance &&
424 feats1.depthClamp == feats2.features.depthClamp && feats1.depthBiasClamp == feats2.features.depthBiasClamp &&
425 feats1.fillModeNonSolid == feats2.features.fillModeNonSolid && feats1.depthBounds == feats2.features.depthBounds &&
426 feats1.wideLines == feats2.features.wideLines && feats1.largePoints == feats2.features.largePoints &&
427 feats1.alphaToOne == feats2.features.alphaToOne && feats1.multiViewport == feats2.features.multiViewport &&
428 feats1.samplerAnisotropy == feats2.features.samplerAnisotropy &&
429 feats1.textureCompressionETC2 == feats2.features.textureCompressionETC2 &&
430 feats1.textureCompressionASTC_LDR == feats2.features.textureCompressionASTC_LDR &&
431 feats1.textureCompressionBC == feats2.features.textureCompressionBC &&
432 feats1.occlusionQueryPrecise == feats2.features.occlusionQueryPrecise &&
433 feats1.pipelineStatisticsQuery == feats2.features.pipelineStatisticsQuery &&
434 feats1.vertexPipelineStoresAndAtomics == feats2.features.vertexPipelineStoresAndAtomics &&
435 feats1.fragmentStoresAndAtomics == feats2.features.fragmentStoresAndAtomics &&
436 feats1.shaderTessellationAndGeometryPointSize == feats2.features.shaderTessellationAndGeometryPointSize &&
437 feats1.shaderImageGatherExtended == feats2.features.shaderImageGatherExtended &&
438 feats1.shaderStorageImageExtendedFormats == feats2.features.shaderStorageImageExtendedFormats &&
439 feats1.shaderStorageImageMultisample == feats2.features.shaderStorageImageMultisample &&
440 feats1.shaderStorageImageReadWithoutFormat == feats2.features.shaderStorageImageReadWithoutFormat &&
441 feats1.shaderStorageImageWriteWithoutFormat == feats2.features.shaderStorageImageWriteWithoutFormat &&
442 feats1.shaderUniformBufferArrayDynamicIndexing == feats2.features.shaderUniformBufferArrayDynamicIndexing &&
443 feats1.shaderSampledImageArrayDynamicIndexing == feats2.features.shaderSampledImageArrayDynamicIndexing &&
444 feats1.shaderStorageBufferArrayDynamicIndexing == feats2.features.shaderStorageBufferArrayDynamicIndexing &&
445 feats1.shaderStorageImageArrayDynamicIndexing == feats2.features.shaderStorageImageArrayDynamicIndexing &&
446 feats1.shaderClipDistance == feats2.features.shaderClipDistance &&
447 feats1.shaderCullDistance == feats2.features.shaderCullDistance &&
448 feats1.shaderFloat64 == feats2.features.shaderFloat64 && feats1.shaderInt64 == feats2.features.shaderInt64 &&
449 feats1.shaderInt16 == feats2.features.shaderInt16 &&
450 feats1.shaderResourceResidency == feats2.features.shaderResourceResidency &&
451 feats1.shaderResourceMinLod == feats2.features.shaderResourceMinLod &&
452 feats1.sparseBinding == feats2.features.sparseBinding &&
453 feats1.sparseResidencyBuffer == feats2.features.sparseResidencyBuffer &&
454 feats1.sparseResidencyImage2D == feats2.features.sparseResidencyImage2D &&
455 feats1.sparseResidencyImage3D == feats2.features.sparseResidencyImage3D &&
456 feats1.sparseResidency2Samples == feats2.features.sparseResidency2Samples &&
457 feats1.sparseResidency4Samples == feats2.features.sparseResidency4Samples &&
458 feats1.sparseResidency8Samples == feats2.features.sparseResidency8Samples &&
459 feats1.sparseResidency16Samples == feats2.features.sparseResidency16Samples &&
460 feats1.sparseResidencyAliased == feats2.features.sparseResidencyAliased &&
461 feats1.variableMultisampleRate == feats2.features.variableMultisampleRate &&
462 feats1.inheritedQueries == feats2.features.inheritedQueries;
463 }
464
465 // Test vkGetPhysicalDeviceFeatures2KHR where nothing supports it.
TEST(LoaderInstPhysDevExts, PhysDevFeats2KHRNoSupport)466 TEST(LoaderInstPhysDevExts, PhysDevFeats2KHRNoSupport) {
467 FrameworkEnvironment env{};
468 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
469 env.get_test_icd(0).physical_devices.push_back({});
470
471 InstWrapper instance(env.vulkan_functions);
472 instance.CheckCreate();
473
474 PFN_vkGetPhysicalDeviceFeatures2KHR GetPhysDevFeats2KHR = instance.load("vkGetPhysicalDeviceFeatures2KHR");
475 ASSERT_EQ(GetPhysDevFeats2KHR, nullptr);
476 }
477
478 // Test vkGetPhysicalDeviceFeatures2KHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevFeatsKHRNoICDSupport)479 TEST(LoaderInstPhysDevExts, PhysDevFeatsKHRNoICDSupport) {
480 FrameworkEnvironment env{};
481 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
482 env.get_test_icd(0).physical_devices.push_back({});
483
484 InstWrapper instance(env.vulkan_functions);
485 instance.create_info.add_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
486 instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
487
488 PFN_vkGetPhysicalDeviceFeatures2KHR GetPhysDevFeats2KHR = instance.load("vkGetPhysicalDeviceFeatures2KHR");
489 ASSERT_EQ(GetPhysDevFeats2KHR, nullptr);
490 }
491
492 // Test vkGetPhysicalDeviceFeatures2KHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, PhysDevFeats2KHRInstanceAndICDSupport)493 TEST(LoaderInstPhysDevExts, PhysDevFeats2KHRInstanceAndICDSupport) {
494 FrameworkEnvironment env{};
495 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
496 env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
497 env.get_test_icd(0).physical_devices.push_back({});
498 FillInRandomFeatures(env.get_test_icd(0).physical_devices.back().features);
499
500 InstWrapper instance(env.vulkan_functions);
501 instance.create_info.add_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
502 instance.CheckCreate();
503
504 PFN_vkGetPhysicalDeviceFeatures2KHR GetPhysDevFeats2KHR = instance.load("vkGetPhysicalDeviceFeatures2KHR");
505 ASSERT_NE(GetPhysDevFeats2KHR, nullptr);
506
507 uint32_t driver_count = 1;
508 VkPhysicalDevice physical_device;
509 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
510 ASSERT_EQ(driver_count, 1U);
511
512 VkPhysicalDeviceFeatures feats{};
513 instance->vkGetPhysicalDeviceFeatures(physical_device, &feats);
514 VkPhysicalDeviceFeatures2 feats2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR};
515 GetPhysDevFeats2KHR(physical_device, &feats2);
516 ASSERT_TRUE(CompareFeatures(feats, feats2));
517 }
518
519 // Test vkGetPhysicalDeviceFeatures2 where instance supports, an ICD, and a device under that ICD
520 // also support, so everything should work and return properly.
521 // Also check if the application didn't enable 1.1 and when a layer 'upgrades' the api version to 1.1
TEST(LoaderInstPhysDevExts, PhysDevFeats2Simple)522 TEST(LoaderInstPhysDevExts, PhysDevFeats2Simple) {
523 FrameworkEnvironment env{};
524 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, VK_API_VERSION_1_1));
525 env.get_test_icd(0).icd_api_version = VK_API_VERSION_1_1;
526 env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
527 env.get_test_icd(0).physical_devices.push_back({});
528 env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
529 env.get_test_icd(0).physical_devices.back().set_api_version(VK_API_VERSION_1_1);
530 FillInRandomFeatures(env.get_test_icd(0).physical_devices.back().features);
531 {
532 InstWrapper instance(env.vulkan_functions);
533 instance.create_info.set_api_version(VK_API_VERSION_1_1);
534 instance.CheckCreate();
535
536 PFN_vkGetPhysicalDeviceFeatures2 GetPhysDevFeats2 = instance.load("vkGetPhysicalDeviceFeatures2");
537 ASSERT_NE(GetPhysDevFeats2, nullptr);
538
539 uint32_t driver_count = 1;
540 VkPhysicalDevice physical_device;
541 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
542 ASSERT_EQ(driver_count, 1U);
543
544 VkPhysicalDeviceFeatures feats{};
545 instance->vkGetPhysicalDeviceFeatures(physical_device, &feats);
546 VkPhysicalDeviceFeatures2 feats2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
547 GetPhysDevFeats2(physical_device, &feats2);
548 ASSERT_TRUE(CompareFeatures(feats, feats2));
549 }
550 { // Now do the same logic but the application didn't enable 1.0 or the extension so they get the emulated call
551 InstWrapper instance(env.vulkan_functions);
552 instance.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
553 instance.CheckCreate();
554 DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
555 CreateDebugUtilsMessenger(log);
556
557 PFN_vkGetPhysicalDeviceFeatures2 GetPhysDevFeats2 = instance.load("vkGetPhysicalDeviceFeatures2");
558 ASSERT_NE(GetPhysDevFeats2, nullptr);
559
560 uint32_t driver_count = 1;
561 VkPhysicalDevice physical_device;
562 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
563 ASSERT_EQ(driver_count, 1U);
564
565 VkPhysicalDeviceFeatures feats{};
566 instance->vkGetPhysicalDeviceFeatures(physical_device, &feats);
567 VkPhysicalDeviceFeatures2 feats2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
568 GetPhysDevFeats2(physical_device, &feats2);
569 ASSERT_TRUE(CompareFeatures(feats, feats2));
570
571 ASSERT_TRUE(log.find("Emulating call in ICD"));
572 }
573 env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
574 .set_name("modify_api_version_layer")
575 .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
576 .set_disable_environment("DisableEnvVar")),
577 "modify_api_version_layer.json");
578 env.get_test_layer().set_alter_api_version(VK_API_VERSION_1_1);
579 { // Now do the same as above but with a layer that updates the version to 1.1 on behalf of the application
580 InstWrapper instance(env.vulkan_functions);
581 instance.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
582 instance.CheckCreate();
583 DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
584 CreateDebugUtilsMessenger(log);
585
586 PFN_vkGetPhysicalDeviceFeatures2 GetPhysDevFeats2 = instance.load("vkGetPhysicalDeviceFeatures2");
587 ASSERT_NE(GetPhysDevFeats2, nullptr);
588
589 uint32_t driver_count = 1;
590 VkPhysicalDevice physical_device;
591 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
592 ASSERT_EQ(driver_count, 1U);
593
594 VkPhysicalDeviceFeatures feats{};
595 instance->vkGetPhysicalDeviceFeatures(physical_device, &feats);
596 VkPhysicalDeviceFeatures2 feats2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
597 GetPhysDevFeats2(physical_device, &feats2);
598 ASSERT_TRUE(CompareFeatures(feats, feats2));
599
600 ASSERT_FALSE(log.find("Emulating call in ICD"));
601 }
602 }
603
604 // Test vkGetPhysicalDeviceFeatures2 and vkGetPhysicalDeviceFeatures2KHR where ICD is 1.0 and supports
605 // extension but the instance supports 1.1 and the extension
TEST(LoaderInstPhysDevExts, PhysDevFeats2KHRInstanceSupports11)606 TEST(LoaderInstPhysDevExts, PhysDevFeats2KHRInstanceSupports11) {
607 FrameworkEnvironment env{};
608 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, VK_API_VERSION_1_0));
609 env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
610 env.get_test_icd(0).physical_devices.push_back({});
611 env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
612 FillInRandomFeatures(env.get_test_icd(0).physical_devices.back().features);
613
614 InstWrapper instance(env.vulkan_functions);
615 instance.create_info.set_api_version(VK_API_VERSION_1_1);
616 instance.create_info.add_extensions(
617 {VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_EXTENSION_NAME});
618 instance.CheckCreate();
619 DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
620 CreateDebugUtilsMessenger(log);
621
622 PFN_vkGetPhysicalDeviceFeatures2KHR GetPhysDevFeats2KHR = instance.load("vkGetPhysicalDeviceFeatures2KHR");
623 ASSERT_NE(GetPhysDevFeats2KHR, nullptr);
624
625 PFN_vkGetPhysicalDeviceFeatures2 GetPhysDevFeats2 = instance.load("vkGetPhysicalDeviceFeatures2");
626 ASSERT_NE(GetPhysDevFeats2, nullptr);
627
628 uint32_t driver_count = 1;
629 VkPhysicalDevice physical_device;
630 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
631 ASSERT_EQ(driver_count, 1U);
632
633 VkPhysicalDeviceFeatures feats{};
634 instance->vkGetPhysicalDeviceFeatures(physical_device, &feats);
635
636 VkPhysicalDeviceFeatures2KHR feats2KHR{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR};
637 GetPhysDevFeats2KHR(physical_device, &feats2KHR);
638 ASSERT_TRUE(CompareFeatures(feats, feats2KHR));
639
640 VkPhysicalDeviceFeatures2 feats2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
641 GetPhysDevFeats2(physical_device, &feats2);
642 ASSERT_TRUE(CompareFeatures(feats, feats2));
643
644 ASSERT_FALSE(log.find("Emulating call in ICD"));
645 }
646
647 // Test vkGetPhysicalDeviceFeatures2 where instance supports it with some ICDs that both support
648 // and don't support it:
649 // ICD 0 supports
650 // Physical device 0 does not
651 // Physical device 1 does
652 // Physical device 2 does not
653 // ICD 1 doesn't support
654 // Physical device 3 does not
655 // ICD 2 supports
656 // Physical device 4 does not
657 // Physical device 5 does not
658 // ICD 3 supports
659 // Physical device 6 does
TEST(LoaderInstPhysDevExts, PhysDevFeatsMixed)660 TEST(LoaderInstPhysDevExts, PhysDevFeatsMixed) {
661 FrameworkEnvironment env{};
662 const uint32_t max_icd_count = 4;
663 const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
664 const uint32_t max_phys_devs = 7;
665
666 for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
667 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, icd != 1 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0));
668 auto& cur_icd = env.get_test_icd(icd);
669
670 // ICD 1 should not have 1.1
671 if (icd != 1) {
672 cur_icd.icd_api_version = VK_API_VERSION_1_1;
673 cur_icd.add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
674 }
675
676 uint32_t rand_vendor_id;
677 uint32_t rand_driver_vers;
678 FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
679
680 for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
681 uint32_t device_version = VK_API_VERSION_1_0;
682 cur_icd.physical_devices.push_back({});
683 auto& cur_dev = cur_icd.physical_devices.back();
684
685 // 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
686 if ((icd == 0 && dev == 1) || icd == 3) {
687 cur_dev.extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
688 device_version = VK_API_VERSION_1_1;
689 }
690
691 // Still set physical device properties (so we can determine if device is correct API version)
692 FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
693 FillInRandomFeatures(cur_dev.features);
694 }
695 }
696
697 InstWrapper instance(env.vulkan_functions);
698 instance.create_info.set_api_version(VK_API_VERSION_1_1);
699 instance.CheckCreate();
700
701 PFN_vkGetPhysicalDeviceFeatures2 GetPhysDevFeats2 = instance.load("vkGetPhysicalDeviceFeatures2");
702 ASSERT_NE(GetPhysDevFeats2, nullptr);
703
704 uint32_t device_count = max_phys_devs;
705 std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
706 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
707 ASSERT_EQ(device_count, max_phys_devs);
708
709 for (uint32_t dev = 0; dev < device_count; ++dev) {
710 VkPhysicalDeviceFeatures feats{};
711 instance->vkGetPhysicalDeviceFeatures(physical_devices[dev], &feats);
712 VkPhysicalDeviceFeatures2 feats2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
713 GetPhysDevFeats2(physical_devices[dev], &feats2);
714 ASSERT_TRUE(CompareFeatures(feats, feats2));
715 }
716 }
717
718 // Fill in random but valid data into the format properties struct for the current physical device
FillInRandomFormatProperties(std::vector<VkFormatProperties>& props)719 void FillInRandomFormatProperties(std::vector<VkFormatProperties>& props) {
720 props.resize(5);
721 for (uint8_t form = 0; form < 5; ++form) {
722 props[form].bufferFeatures = static_cast<VkFormatFeatureFlags>(rand());
723 props[form].linearTilingFeatures = static_cast<VkFormatFeatureFlags>(rand());
724 props[form].optimalTilingFeatures = static_cast<VkFormatFeatureFlags>(rand());
725 }
726 }
727
728 // Test vkGetPhysicalDeviceFormatProperties2KHR where nothing supports it.
TEST(LoaderInstPhysDevExts, PhysDevFormatProps2KHRNoSupport)729 TEST(LoaderInstPhysDevExts, PhysDevFormatProps2KHRNoSupport) {
730 FrameworkEnvironment env{};
731 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
732 env.get_test_icd(0).physical_devices.push_back({});
733
734 InstWrapper instance(env.vulkan_functions);
735 instance.CheckCreate();
736
737 PFN_vkGetPhysicalDeviceFormatProperties2KHR GetPhysDevFormatProps2KHR =
738 instance.load("vkGetPhysicalDeviceFormatProperties2KHR");
739 ASSERT_EQ(GetPhysDevFormatProps2KHR, nullptr);
740 }
741
742 // Test vkGetPhysicalDeviceFormatProperties2KHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevFormatPropsKHRNoICDSupport)743 TEST(LoaderInstPhysDevExts, PhysDevFormatPropsKHRNoICDSupport) {
744 FrameworkEnvironment env{};
745 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
746 env.get_test_icd(0).physical_devices.push_back({});
747
748 InstWrapper instance(env.vulkan_functions);
749 instance.create_info.add_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
750 instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
751
752 PFN_vkGetPhysicalDeviceFormatProperties2KHR GetPhysDevFormatProps2KHR =
753 instance.load("vkGetPhysicalDeviceFormatProperties2KHR");
754 ASSERT_EQ(GetPhysDevFormatProps2KHR, nullptr);
755 }
756
757 // Test vkGetPhysicalDeviceFormatProperties2KHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, PhysDevFormatProps2KHRInstanceAndICDSupport)758 TEST(LoaderInstPhysDevExts, PhysDevFormatProps2KHRInstanceAndICDSupport) {
759 FrameworkEnvironment env{};
760 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
761 env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
762 env.get_test_icd(0).physical_devices.push_back({});
763 FillInRandomFormatProperties(env.get_test_icd(0).physical_devices.back().format_properties);
764
765 InstWrapper instance(env.vulkan_functions);
766 instance.create_info.add_extensions(
767 {VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_EXTENSION_NAME});
768 instance.CheckCreate();
769 DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
770 CreateDebugUtilsMessenger(log);
771
772 PFN_vkGetPhysicalDeviceFormatProperties2KHR GetPhysDevFormatProps2KHR =
773 instance.load("vkGetPhysicalDeviceFormatProperties2KHR");
774 ASSERT_NE(GetPhysDevFormatProps2KHR, nullptr);
775
776 uint32_t driver_count = 1;
777 VkPhysicalDevice physical_device;
778 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
779 ASSERT_EQ(driver_count, 1U);
780
781 VkFormatProperties props{};
782 instance->vkGetPhysicalDeviceFormatProperties(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, &props);
783 VkFormatProperties2 props2{VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2};
784 GetPhysDevFormatProps2KHR(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, &props2);
785
786 ASSERT_EQ(props.bufferFeatures, props2.formatProperties.bufferFeatures);
787 ASSERT_EQ(props.linearTilingFeatures, props2.formatProperties.linearTilingFeatures);
788 ASSERT_EQ(props.optimalTilingFeatures, props2.formatProperties.optimalTilingFeatures);
789 }
790
791 // Test vkGetPhysicalDeviceFormatProperties2 where instance supports, an ICD, and a device under that ICD
792 // also support, so everything should work and return properly.
793 // Also check if the application didn't enable 1.1 and when a layer 'upgrades' the api version to 1.1
TEST(LoaderInstPhysDevExts, PhysDevFormatProps2Simple)794 TEST(LoaderInstPhysDevExts, PhysDevFormatProps2Simple) {
795 FrameworkEnvironment env{};
796 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, VK_API_VERSION_1_1));
797 env.get_test_icd(0).icd_api_version = VK_API_VERSION_1_1;
798 env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
799 env.get_test_icd(0).physical_devices.push_back({});
800 env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
801 env.get_test_icd(0).physical_devices.back().set_api_version(VK_API_VERSION_1_1);
802 FillInRandomFormatProperties(env.get_test_icd(0).physical_devices.back().format_properties);
803 {
804 InstWrapper instance(env.vulkan_functions);
805 instance.create_info.set_api_version(VK_API_VERSION_1_1);
806 instance.CheckCreate();
807
808 PFN_vkGetPhysicalDeviceFormatProperties2 GetPhysDevFormatProps2 = instance.load("vkGetPhysicalDeviceFormatProperties2");
809 ASSERT_NE(GetPhysDevFormatProps2, nullptr);
810
811 uint32_t driver_count = 1;
812 VkPhysicalDevice physical_device;
813 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
814 ASSERT_EQ(driver_count, 1U);
815
816 VkFormatProperties props{};
817 instance->vkGetPhysicalDeviceFormatProperties(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, &props);
818 VkFormatProperties2 props2{VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2};
819 GetPhysDevFormatProps2(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, &props2);
820
821 ASSERT_EQ(props.bufferFeatures, props2.formatProperties.bufferFeatures);
822 ASSERT_EQ(props.linearTilingFeatures, props2.formatProperties.linearTilingFeatures);
823 ASSERT_EQ(props.optimalTilingFeatures, props2.formatProperties.optimalTilingFeatures);
824 }
825 { // Do the same logic but have the application forget to enable 1.1 and doesn't enable the extension
826 InstWrapper instance(env.vulkan_functions);
827 instance.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
828 instance.CheckCreate();
829 DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
830 CreateDebugUtilsMessenger(log);
831
832 PFN_vkGetPhysicalDeviceFormatProperties2 GetPhysDevFormatProps2 = instance.load("vkGetPhysicalDeviceFormatProperties2");
833 ASSERT_NE(GetPhysDevFormatProps2, nullptr);
834
835 uint32_t driver_count = 1;
836 VkPhysicalDevice physical_device;
837 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
838 ASSERT_EQ(driver_count, 1U);
839
840 VkFormatProperties props{};
841 instance->vkGetPhysicalDeviceFormatProperties(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, &props);
842 VkFormatProperties2 props2{VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2};
843 GetPhysDevFormatProps2(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, &props2);
844
845 ASSERT_EQ(props.bufferFeatures, props2.formatProperties.bufferFeatures);
846 ASSERT_EQ(props.linearTilingFeatures, props2.formatProperties.linearTilingFeatures);
847 ASSERT_EQ(props.optimalTilingFeatures, props2.formatProperties.optimalTilingFeatures);
848 ASSERT_TRUE(log.find("Emulating call in ICD"));
849 }
850 env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
851 .set_name("modify_api_version_layer")
852 .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
853 .set_disable_environment("DisableEnvVar")),
854 "modify_api_version_layer.json");
855 env.get_test_layer().set_alter_api_version(VK_API_VERSION_1_1);
856 { // Now do the same as above but with a layer that updates the version to 1.1 on behalf of the application
857 InstWrapper instance(env.vulkan_functions);
858 instance.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
859 instance.CheckCreate();
860 DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
861 CreateDebugUtilsMessenger(log);
862
863 PFN_vkGetPhysicalDeviceFormatProperties2 GetPhysDevFormatProps2 = instance.load("vkGetPhysicalDeviceFormatProperties2");
864 ASSERT_NE(GetPhysDevFormatProps2, nullptr);
865
866 uint32_t driver_count = 1;
867 VkPhysicalDevice physical_device;
868 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
869 ASSERT_EQ(driver_count, 1U);
870
871 VkFormatProperties props{};
872 instance->vkGetPhysicalDeviceFormatProperties(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, &props);
873 VkFormatProperties2 props2{VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2};
874 GetPhysDevFormatProps2(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, &props2);
875
876 ASSERT_EQ(props.bufferFeatures, props2.formatProperties.bufferFeatures);
877 ASSERT_EQ(props.linearTilingFeatures, props2.formatProperties.linearTilingFeatures);
878 ASSERT_EQ(props.optimalTilingFeatures, props2.formatProperties.optimalTilingFeatures);
879 ASSERT_FALSE(log.find("Emulating call in ICD"));
880 }
881 }
882 // Test vkGetPhysicalDeviceFormatProperties2 and vkGetPhysicalDeviceFormatProperties2KHR where ICD is 1.0 and supports
883 // extension but the instance supports 1.1 and the extension
TEST(LoaderInstPhysDevExts, PhysDevFormatProps2KHRInstanceSupports11)884 TEST(LoaderInstPhysDevExts, PhysDevFormatProps2KHRInstanceSupports11) {
885 FrameworkEnvironment env{};
886 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
887 env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
888 env.get_test_icd(0).physical_devices.push_back({});
889 env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
890 FillInRandomFormatProperties(env.get_test_icd(0).physical_devices.back().format_properties);
891
892 InstWrapper instance(env.vulkan_functions);
893 instance.create_info.set_api_version(VK_API_VERSION_1_1);
894 instance.create_info.add_extensions(
895 {VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_EXTENSION_NAME});
896 instance.CheckCreate();
897 DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
898 CreateDebugUtilsMessenger(log);
899
900 PFN_vkGetPhysicalDeviceFormatProperties2 GetPhysDevFormatProps2 = instance.load("vkGetPhysicalDeviceFormatProperties2");
901 ASSERT_NE(GetPhysDevFormatProps2, nullptr);
902
903 PFN_vkGetPhysicalDeviceFormatProperties2KHR GetPhysDevFormatProps2KHR =
904 instance.load("vkGetPhysicalDeviceFormatProperties2KHR");
905 ASSERT_NE(GetPhysDevFormatProps2KHR, nullptr);
906
907 uint32_t driver_count = 1;
908 VkPhysicalDevice physical_device;
909 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
910 ASSERT_EQ(driver_count, 1U);
911
912 VkFormatProperties props{};
913 instance->vkGetPhysicalDeviceFormatProperties(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, &props);
914 VkFormatProperties2 props2{VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2};
915 GetPhysDevFormatProps2(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, &props2);
916
917 ASSERT_EQ(props.bufferFeatures, props2.formatProperties.bufferFeatures);
918 ASSERT_EQ(props.linearTilingFeatures, props2.formatProperties.linearTilingFeatures);
919 ASSERT_EQ(props.optimalTilingFeatures, props2.formatProperties.optimalTilingFeatures);
920
921 VkFormatProperties2KHR props2KHR{VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2};
922 GetPhysDevFormatProps2KHR(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, &props2KHR);
923
924 ASSERT_EQ(props.bufferFeatures, props2KHR.formatProperties.bufferFeatures);
925 ASSERT_EQ(props.linearTilingFeatures, props2KHR.formatProperties.linearTilingFeatures);
926 ASSERT_EQ(props.optimalTilingFeatures, props2KHR.formatProperties.optimalTilingFeatures);
927
928 ASSERT_FALSE(log.find("Emulating call in ICD"));
929 }
930
931 // Test vkGetPhysicalDeviceFormatProperties2 where instance supports it with some ICDs that both support
932 // and don't support it:
933 // ICD 0 supports
934 // Physical device 0 does not
935 // Physical device 1 does
936 // Physical device 2 does not
937 // ICD 1 doesn't support
938 // Physical device 3 does not
939 // ICD 2 supports
940 // Physical device 4 does not
941 // Physical device 5 does not
942 // ICD 3 supports
943 // Physical device 6 does
TEST(LoaderInstPhysDevExts, PhysDevFormatPropsMixed)944 TEST(LoaderInstPhysDevExts, PhysDevFormatPropsMixed) {
945 FrameworkEnvironment env{};
946 const uint32_t max_icd_count = 4;
947 const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
948 const uint32_t max_phys_devs = 7;
949
950 for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
951 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, icd != 1 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0));
952 auto& cur_icd = env.get_test_icd(icd);
953
954 // ICD 1 should not have 1.1
955 if (icd != 1) {
956 cur_icd.icd_api_version = VK_API_VERSION_1_1;
957 cur_icd.add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
958 }
959
960 uint32_t rand_vendor_id;
961 uint32_t rand_driver_vers;
962 FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
963
964 for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
965 uint32_t device_version = VK_API_VERSION_1_0;
966 cur_icd.physical_devices.push_back({});
967 auto& cur_dev = cur_icd.physical_devices.back();
968
969 // 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
970 if ((icd == 0 && dev == 1) || icd == 3) {
971 cur_dev.extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
972 device_version = VK_API_VERSION_1_1;
973 }
974
975 // Still set physical device properties (so we can determine if device is correct API version)
976 FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
977 FillInRandomFormatProperties(cur_dev.format_properties);
978 }
979 }
980
981 InstWrapper instance(env.vulkan_functions);
982 instance.create_info.set_api_version(VK_API_VERSION_1_1);
983 instance.CheckCreate();
984
985 PFN_vkGetPhysicalDeviceFormatProperties2 GetPhysDevFormatProps2 = instance.load("vkGetPhysicalDeviceFormatProperties2");
986 ASSERT_NE(GetPhysDevFormatProps2, nullptr);
987
988 uint32_t device_count = max_phys_devs;
989 std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
990 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
991 ASSERT_EQ(device_count, max_phys_devs);
992
993 for (uint32_t dev = 0; dev < device_count; ++dev) {
994 VkFormat format = static_cast<VkFormat>((dev + 1) % 5);
995 VkFormatProperties props{};
996 instance->vkGetPhysicalDeviceFormatProperties(physical_devices[dev], format, &props);
997 VkFormatProperties2 props2{VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2};
998 GetPhysDevFormatProps2(physical_devices[dev], format, &props2);
999
1000 ASSERT_EQ(props.bufferFeatures, props2.formatProperties.bufferFeatures);
1001 ASSERT_EQ(props.linearTilingFeatures, props2.formatProperties.linearTilingFeatures);
1002 ASSERT_EQ(props.optimalTilingFeatures, props2.formatProperties.optimalTilingFeatures);
1003 }
1004 }
1005
1006 // Fill in random but valid data into the image format data struct for the current physical device
FillInRandomImageFormatData(VkImageFormatProperties& props)1007 void FillInRandomImageFormatData(VkImageFormatProperties& props) {
1008 props.maxExtent = {static_cast<uint32_t>(rand() % 512), static_cast<uint32_t>(rand() % 512),
1009 static_cast<uint32_t>(rand() % 512)};
1010 props.maxMipLevels = static_cast<uint32_t>(1 << (rand() % 16));
1011 props.maxArrayLayers = static_cast<uint32_t>(1 << (rand() % 16));
1012 props.sampleCounts = static_cast<VkSampleCountFlags>(1 << (rand() % 7));
1013 props.maxResourceSize = static_cast<uint64_t>(rand());
1014 }
1015
1016 // Test vkGetPhysicalDeviceImageFormatProperties2KHR where nothing supports it.
TEST(LoaderInstPhysDevExts, PhysDevImageFormatProps2KHRNoSupport)1017 TEST(LoaderInstPhysDevExts, PhysDevImageFormatProps2KHRNoSupport) {
1018 FrameworkEnvironment env{};
1019 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
1020 env.get_test_icd(0).physical_devices.push_back({});
1021
1022 InstWrapper instance(env.vulkan_functions);
1023 instance.CheckCreate();
1024
1025 PFN_vkGetPhysicalDeviceImageFormatProperties2KHR GetPhysDevImageFormatProps2 =
1026 instance.load("vkGetPhysicalDeviceImageFormatProperties2KHR");
1027 ASSERT_EQ(GetPhysDevImageFormatProps2, nullptr);
1028 }
1029
1030 // Test vkGetPhysicalDeviceImageFormatProperties2KHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevImageFormatPropsKHRNoICDSupport)1031 TEST(LoaderInstPhysDevExts, PhysDevImageFormatPropsKHRNoICDSupport) {
1032 FrameworkEnvironment env{};
1033 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
1034 env.get_test_icd(0).physical_devices.push_back({});
1035
1036 InstWrapper instance(env.vulkan_functions);
1037 instance.create_info.add_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
1038 instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
1039
1040 PFN_vkGetPhysicalDeviceImageFormatProperties2KHR GetPhysDevImageFormatProps2KHR =
1041 instance.load("vkGetPhysicalDeviceImageFormatProperties2KHR");
1042 ASSERT_EQ(GetPhysDevImageFormatProps2KHR, nullptr);
1043 }
1044
1045 // Test vkGetPhysicalDeviceImageFormatProperties2KHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, PhysDevImageFormatProps2KHRInstanceAndICDSupport)1046 TEST(LoaderInstPhysDevExts, PhysDevImageFormatProps2KHRInstanceAndICDSupport) {
1047 FrameworkEnvironment env{};
1048 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
1049 env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
1050 env.get_test_icd(0).physical_devices.push_back({});
1051 FillInRandomImageFormatData(env.get_test_icd(0).physical_devices.back().image_format_properties);
1052
1053 InstWrapper instance(env.vulkan_functions);
1054 instance.create_info.add_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
1055 instance.CheckCreate();
1056
1057 PFN_vkGetPhysicalDeviceImageFormatProperties2KHR GetPhysDevImageFormatProps2KHR =
1058 instance.load("vkGetPhysicalDeviceImageFormatProperties2KHR");
1059 ASSERT_NE(GetPhysDevImageFormatProps2KHR, nullptr);
1060
1061 uint32_t driver_count = 1;
1062 VkPhysicalDevice physical_device;
1063 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
1064 ASSERT_EQ(driver_count, 1U);
1065
1066 VkImageFormatProperties props{};
1067 ASSERT_EQ(VK_SUCCESS,
1068 instance->vkGetPhysicalDeviceImageFormatProperties(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, VK_IMAGE_TYPE_2D,
1069 VK_IMAGE_TILING_OPTIMAL, 0, 0, &props));
1070
1071 VkPhysicalDeviceImageFormatInfo2 info2{
1072 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, // sType
1073 nullptr, // pNext
1074 VK_FORMAT_R4G4_UNORM_PACK8, // format
1075 VK_IMAGE_TYPE_2D, // type
1076 VK_IMAGE_TILING_OPTIMAL, // tiling
1077 0, // usage
1078 0, // flags
1079 };
1080 VkImageFormatProperties2 props2{VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2};
1081 ASSERT_EQ(VK_SUCCESS, GetPhysDevImageFormatProps2KHR(physical_device, &info2, &props2));
1082
1083 ASSERT_EQ(props.maxExtent.width, props2.imageFormatProperties.maxExtent.width);
1084 ASSERT_EQ(props.maxExtent.height, props2.imageFormatProperties.maxExtent.height);
1085 ASSERT_EQ(props.maxExtent.depth, props2.imageFormatProperties.maxExtent.depth);
1086 ASSERT_EQ(props.maxMipLevels, props2.imageFormatProperties.maxMipLevels);
1087 ASSERT_EQ(props.maxArrayLayers, props2.imageFormatProperties.maxArrayLayers);
1088 ASSERT_EQ(props.sampleCounts, props2.imageFormatProperties.sampleCounts);
1089 ASSERT_EQ(props.maxResourceSize, props2.imageFormatProperties.maxResourceSize);
1090 }
1091
1092 // Test vkGetPhysicalDeviceImageFormatProperties2 where instance supports, an ICD, and a device under that ICD
1093 // also support, so everything should work and return properly.
1094 // Also check if the application didn't enable 1.1 and when a layer 'upgrades' the api version to 1.1
TEST(LoaderInstPhysDevExts, PhysDevImageFormatProps2Simple)1095 TEST(LoaderInstPhysDevExts, PhysDevImageFormatProps2Simple) {
1096 FrameworkEnvironment env{};
1097 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
1098 env.get_test_icd(0).icd_api_version = VK_API_VERSION_1_1;
1099 env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
1100 env.get_test_icd(0).physical_devices.push_back({});
1101 env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
1102 FillInRandomImageFormatData(env.get_test_icd(0).physical_devices.back().image_format_properties);
1103 {
1104 InstWrapper instance(env.vulkan_functions);
1105 instance.create_info.set_api_version(VK_API_VERSION_1_1);
1106 instance.CheckCreate();
1107
1108 PFN_vkGetPhysicalDeviceImageFormatProperties2 GetPhysDevImageFormatProps2 =
1109 instance.load("vkGetPhysicalDeviceImageFormatProperties2");
1110 ASSERT_NE(GetPhysDevImageFormatProps2, nullptr);
1111
1112 uint32_t driver_count = 1;
1113 VkPhysicalDevice physical_device;
1114 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
1115 ASSERT_EQ(driver_count, 1U);
1116
1117 VkImageFormatProperties props{};
1118 ASSERT_EQ(VK_SUCCESS,
1119 instance->vkGetPhysicalDeviceImageFormatProperties(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, VK_IMAGE_TYPE_2D,
1120 VK_IMAGE_TILING_OPTIMAL, 0, 0, &props));
1121
1122 VkPhysicalDeviceImageFormatInfo2 info2{
1123 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, // sType
1124 nullptr, // pNext
1125 VK_FORMAT_R4G4_UNORM_PACK8, // format
1126 VK_IMAGE_TYPE_2D, // type
1127 VK_IMAGE_TILING_OPTIMAL, // tiling
1128 0, // usage
1129 0, // flags
1130 };
1131
1132 VkImageFormatProperties2 props2{VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2};
1133 ASSERT_EQ(VK_SUCCESS, GetPhysDevImageFormatProps2(physical_device, &info2, &props2));
1134
1135 ASSERT_EQ(props.maxExtent.width, props2.imageFormatProperties.maxExtent.width);
1136 ASSERT_EQ(props.maxExtent.height, props2.imageFormatProperties.maxExtent.height);
1137 ASSERT_EQ(props.maxExtent.depth, props2.imageFormatProperties.maxExtent.depth);
1138 ASSERT_EQ(props.maxMipLevels, props2.imageFormatProperties.maxMipLevels);
1139 ASSERT_EQ(props.maxArrayLayers, props2.imageFormatProperties.maxArrayLayers);
1140 ASSERT_EQ(props.sampleCounts, props2.imageFormatProperties.sampleCounts);
1141 ASSERT_EQ(props.maxResourceSize, props2.imageFormatProperties.maxResourceSize);
1142 }
1143 { // Now do the same logic but the application didn't enable 1.0 or the extension so they get the emulated call
1144 InstWrapper instance(env.vulkan_functions);
1145 instance.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
1146 instance.CheckCreate();
1147 DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
1148 CreateDebugUtilsMessenger(log);
1149
1150 PFN_vkGetPhysicalDeviceImageFormatProperties2 GetPhysDevImageFormatProps2 =
1151 instance.load("vkGetPhysicalDeviceImageFormatProperties2");
1152 ASSERT_NE(GetPhysDevImageFormatProps2, nullptr);
1153
1154 uint32_t driver_count = 1;
1155 VkPhysicalDevice physical_device;
1156 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
1157 ASSERT_EQ(driver_count, 1U);
1158
1159 VkImageFormatProperties props{};
1160 ASSERT_EQ(VK_SUCCESS,
1161 instance->vkGetPhysicalDeviceImageFormatProperties(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, VK_IMAGE_TYPE_2D,
1162 VK_IMAGE_TILING_OPTIMAL, 0, 0, &props));
1163
1164 VkPhysicalDeviceImageFormatInfo2 info2{
1165 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, // sType
1166 nullptr, // pNext
1167 VK_FORMAT_R4G4_UNORM_PACK8, // format
1168 VK_IMAGE_TYPE_2D, // type
1169 VK_IMAGE_TILING_OPTIMAL, // tiling
1170 0, // usage
1171 0, // flags
1172 };
1173
1174 VkImageFormatProperties2 props2{VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2};
1175 ASSERT_EQ(VK_SUCCESS, GetPhysDevImageFormatProps2(physical_device, &info2, &props2));
1176
1177 ASSERT_EQ(props.maxExtent.width, props2.imageFormatProperties.maxExtent.width);
1178 ASSERT_EQ(props.maxExtent.height, props2.imageFormatProperties.maxExtent.height);
1179 ASSERT_EQ(props.maxExtent.depth, props2.imageFormatProperties.maxExtent.depth);
1180 ASSERT_EQ(props.maxMipLevels, props2.imageFormatProperties.maxMipLevels);
1181 ASSERT_EQ(props.maxArrayLayers, props2.imageFormatProperties.maxArrayLayers);
1182 ASSERT_EQ(props.sampleCounts, props2.imageFormatProperties.sampleCounts);
1183 ASSERT_EQ(props.maxResourceSize, props2.imageFormatProperties.maxResourceSize);
1184 ASSERT_TRUE(log.find("Emulating call in ICD"));
1185 }
1186 env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
1187 .set_name("modify_api_version_layer")
1188 .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
1189 .set_disable_environment("DisableEnvVar")),
1190 "modify_api_version_layer.json");
1191 env.get_test_layer().set_alter_api_version(VK_API_VERSION_1_1);
1192 { // Now do the same as above but with a layer that updates the version to 1.1 on behalf of the application
1193 InstWrapper instance(env.vulkan_functions);
1194 instance.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
1195 instance.CheckCreate();
1196 DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
1197 CreateDebugUtilsMessenger(log);
1198
1199 PFN_vkGetPhysicalDeviceImageFormatProperties2 GetPhysDevImageFormatProps2 =
1200 instance.load("vkGetPhysicalDeviceImageFormatProperties2");
1201 ASSERT_NE(GetPhysDevImageFormatProps2, nullptr);
1202
1203 uint32_t driver_count = 1;
1204 VkPhysicalDevice physical_device;
1205 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
1206 ASSERT_EQ(driver_count, 1U);
1207
1208 VkImageFormatProperties props{};
1209 ASSERT_EQ(VK_SUCCESS,
1210 instance->vkGetPhysicalDeviceImageFormatProperties(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, VK_IMAGE_TYPE_2D,
1211 VK_IMAGE_TILING_OPTIMAL, 0, 0, &props));
1212
1213 VkPhysicalDeviceImageFormatInfo2 info2{
1214 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, // sType
1215 nullptr, // pNext
1216 VK_FORMAT_R4G4_UNORM_PACK8, // format
1217 VK_IMAGE_TYPE_2D, // type
1218 VK_IMAGE_TILING_OPTIMAL, // tiling
1219 0, // usage
1220 0, // flags
1221 };
1222
1223 VkImageFormatProperties2 props2{VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2};
1224 ASSERT_EQ(VK_SUCCESS, GetPhysDevImageFormatProps2(physical_device, &info2, &props2));
1225
1226 ASSERT_EQ(props.maxExtent.width, props2.imageFormatProperties.maxExtent.width);
1227 ASSERT_EQ(props.maxExtent.height, props2.imageFormatProperties.maxExtent.height);
1228 ASSERT_EQ(props.maxExtent.depth, props2.imageFormatProperties.maxExtent.depth);
1229 ASSERT_EQ(props.maxMipLevels, props2.imageFormatProperties.maxMipLevels);
1230 ASSERT_EQ(props.maxArrayLayers, props2.imageFormatProperties.maxArrayLayers);
1231 ASSERT_EQ(props.sampleCounts, props2.imageFormatProperties.sampleCounts);
1232 ASSERT_EQ(props.maxResourceSize, props2.imageFormatProperties.maxResourceSize);
1233 ASSERT_FALSE(log.find("Emulating call in ICD"));
1234 }
1235 }
1236
1237 // Test vkGetPhysicalDeviceImageFormatProperties2 and vkGetPhysicalDeviceImageFormatProperties2KHR where instance supports, an ICD,
1238 // and a device under that ICD also support, so everything should work and return properly.
TEST(LoaderInstPhysDevExts, PhysDevImageFormatProps2KHRInstanceSupports11)1239 TEST(LoaderInstPhysDevExts, PhysDevImageFormatProps2KHRInstanceSupports11) {
1240 FrameworkEnvironment env{};
1241 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
1242 env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
1243 env.get_test_icd(0).physical_devices.push_back({});
1244 env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
1245 FillInRandomImageFormatData(env.get_test_icd(0).physical_devices.back().image_format_properties);
1246
1247 InstWrapper instance(env.vulkan_functions);
1248 instance.create_info.set_api_version(VK_API_VERSION_1_1);
1249 instance.create_info.add_extensions(
1250 {VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_EXTENSION_NAME});
1251 instance.CheckCreate();
1252 DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
1253 CreateDebugUtilsMessenger(log);
1254
1255 PFN_vkGetPhysicalDeviceImageFormatProperties2 GetPhysDevImageFormatProps2 =
1256 instance.load("vkGetPhysicalDeviceImageFormatProperties2");
1257 ASSERT_NE(GetPhysDevImageFormatProps2, nullptr);
1258
1259 PFN_vkGetPhysicalDeviceImageFormatProperties2KHR GetPhysDevImageFormatProps2KHR =
1260 instance.load("vkGetPhysicalDeviceImageFormatProperties2KHR");
1261 ASSERT_NE(GetPhysDevImageFormatProps2KHR, nullptr);
1262
1263 uint32_t driver_count = 1;
1264 VkPhysicalDevice physical_device;
1265 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
1266 ASSERT_EQ(driver_count, 1U);
1267
1268 VkImageFormatProperties props{};
1269 ASSERT_EQ(VK_SUCCESS,
1270 instance->vkGetPhysicalDeviceImageFormatProperties(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, VK_IMAGE_TYPE_2D,
1271 VK_IMAGE_TILING_OPTIMAL, 0, 0, &props));
1272
1273 VkPhysicalDeviceImageFormatInfo2 info2{
1274 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, // sType
1275 nullptr, // pNext
1276 VK_FORMAT_R4G4_UNORM_PACK8, // format
1277 VK_IMAGE_TYPE_2D, // type
1278 VK_IMAGE_TILING_OPTIMAL, // tiling
1279 0, // usage
1280 0, // flags
1281 };
1282
1283 VkImageFormatProperties2 props2{VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2};
1284 ASSERT_EQ(VK_SUCCESS, GetPhysDevImageFormatProps2(physical_device, &info2, &props2));
1285
1286 ASSERT_EQ(props.maxExtent.width, props2.imageFormatProperties.maxExtent.width);
1287 ASSERT_EQ(props.maxExtent.height, props2.imageFormatProperties.maxExtent.height);
1288 ASSERT_EQ(props.maxExtent.depth, props2.imageFormatProperties.maxExtent.depth);
1289 ASSERT_EQ(props.maxMipLevels, props2.imageFormatProperties.maxMipLevels);
1290 ASSERT_EQ(props.maxArrayLayers, props2.imageFormatProperties.maxArrayLayers);
1291 ASSERT_EQ(props.sampleCounts, props2.imageFormatProperties.sampleCounts);
1292 ASSERT_EQ(props.maxResourceSize, props2.imageFormatProperties.maxResourceSize);
1293
1294 VkImageFormatProperties2KHR props2KHR{VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR};
1295 ASSERT_EQ(VK_SUCCESS, GetPhysDevImageFormatProps2KHR(physical_device, &info2, &props2KHR));
1296
1297 ASSERT_EQ(props.maxExtent.width, props2KHR.imageFormatProperties.maxExtent.width);
1298 ASSERT_EQ(props.maxExtent.height, props2KHR.imageFormatProperties.maxExtent.height);
1299 ASSERT_EQ(props.maxExtent.depth, props2KHR.imageFormatProperties.maxExtent.depth);
1300 ASSERT_EQ(props.maxMipLevels, props2KHR.imageFormatProperties.maxMipLevels);
1301 ASSERT_EQ(props.maxArrayLayers, props2KHR.imageFormatProperties.maxArrayLayers);
1302 ASSERT_EQ(props.sampleCounts, props2KHR.imageFormatProperties.sampleCounts);
1303 ASSERT_EQ(props.maxResourceSize, props2KHR.imageFormatProperties.maxResourceSize);
1304
1305 ASSERT_FALSE(log.find("Emulating call in ICD"));
1306 }
1307
1308 // Test vkGetPhysicalDeviceImageFormatProperties2 where instance supports it with some ICDs that both support
1309 // and don't support it:
1310 // ICD 0 supports
1311 // Physical device 0 does not
1312 // Physical device 1 does
1313 // Physical device 2 does not
1314 // ICD 1 doesn't support
1315 // Physical device 3 does not
1316 // ICD 2 supports
1317 // Physical device 4 does not
1318 // Physical device 5 does not
1319 // ICD 3 supports
1320 // Physical device 6 does
TEST(LoaderInstPhysDevExts, PhysDevImageFormatPropsMixed)1321 TEST(LoaderInstPhysDevExts, PhysDevImageFormatPropsMixed) {
1322 FrameworkEnvironment env{};
1323 const uint32_t max_icd_count = 4;
1324 const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
1325 const uint32_t max_phys_devs = 7;
1326
1327 for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
1328 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, icd != 1 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0));
1329 auto& cur_icd = env.get_test_icd(icd);
1330
1331 // ICD 1 should not have 1.1
1332 if (icd != 1) {
1333 cur_icd.icd_api_version = VK_API_VERSION_1_1;
1334 cur_icd.add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
1335 }
1336
1337 uint32_t rand_vendor_id;
1338 uint32_t rand_driver_vers;
1339 FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
1340
1341 for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
1342 uint32_t device_version = VK_API_VERSION_1_0;
1343 cur_icd.physical_devices.push_back({});
1344 auto& cur_dev = cur_icd.physical_devices.back();
1345
1346 // 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
1347 if ((icd == 0 && dev == 1) || icd == 3) {
1348 cur_dev.extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
1349 device_version = VK_API_VERSION_1_1;
1350 }
1351
1352 // Still set physical device properties (so we can determine if device is correct API version)
1353 FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
1354 FillInRandomImageFormatData(cur_dev.image_format_properties);
1355 }
1356 }
1357
1358 InstWrapper instance(env.vulkan_functions);
1359 instance.create_info.set_api_version(VK_API_VERSION_1_1);
1360 instance.CheckCreate();
1361
1362 PFN_vkGetPhysicalDeviceImageFormatProperties2 GetPhysDevImageFormatProps2 =
1363 instance.load("vkGetPhysicalDeviceImageFormatProperties2");
1364 ASSERT_NE(GetPhysDevImageFormatProps2, nullptr);
1365
1366 uint32_t device_count = max_phys_devs;
1367 std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
1368 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
1369 ASSERT_EQ(device_count, max_phys_devs);
1370
1371 for (uint32_t dev = 0; dev < device_count; ++dev) {
1372 VkImageFormatProperties props{};
1373 ASSERT_EQ(VK_SUCCESS,
1374 instance->vkGetPhysicalDeviceImageFormatProperties(physical_devices[dev], VK_FORMAT_R4G4_UNORM_PACK8,
1375 VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, 0, 0, &props));
1376
1377 VkPhysicalDeviceImageFormatInfo2 info2{
1378 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, // sType
1379 nullptr, // pNext
1380 VK_FORMAT_R4G4_UNORM_PACK8, // format
1381 VK_IMAGE_TYPE_2D, // type
1382 VK_IMAGE_TILING_OPTIMAL, // tiling
1383 0, // usage
1384 0, // flags
1385 };
1386 VkImageFormatProperties2 props2{VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2};
1387 ASSERT_EQ(VK_SUCCESS, GetPhysDevImageFormatProps2(physical_devices[dev], &info2, &props2));
1388
1389 ASSERT_EQ(props.maxExtent.width, props2.imageFormatProperties.maxExtent.width);
1390 ASSERT_EQ(props.maxExtent.height, props2.imageFormatProperties.maxExtent.height);
1391 ASSERT_EQ(props.maxExtent.depth, props2.imageFormatProperties.maxExtent.depth);
1392 ASSERT_EQ(props.maxMipLevels, props2.imageFormatProperties.maxMipLevels);
1393 ASSERT_EQ(props.maxArrayLayers, props2.imageFormatProperties.maxArrayLayers);
1394 ASSERT_EQ(props.sampleCounts, props2.imageFormatProperties.sampleCounts);
1395 ASSERT_EQ(props.maxResourceSize, props2.imageFormatProperties.maxResourceSize);
1396 }
1397 }
1398
1399 // Test vkGetPhysicalDeviceMemoryProperties2KHR where nothing supports it.
TEST(LoaderInstPhysDevExts, PhysDevMemoryProps2KHRNoSupport)1400 TEST(LoaderInstPhysDevExts, PhysDevMemoryProps2KHRNoSupport) {
1401 FrameworkEnvironment env{};
1402 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
1403 env.get_test_icd(0).physical_devices.push_back({});
1404
1405 InstWrapper instance(env.vulkan_functions);
1406 instance.CheckCreate();
1407
1408 PFN_vkGetPhysicalDeviceMemoryProperties2KHR GetPhysDevMemoryProps2KHR =
1409 instance.load("vkGetPhysicalDeviceMemoryProperties2KHR");
1410 ASSERT_EQ(GetPhysDevMemoryProps2KHR, nullptr);
1411 }
1412
1413 // Test vkGetPhysicalDeviceMemoryProperties2KHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevMemoryPropsKHRNoICDSupport)1414 TEST(LoaderInstPhysDevExts, PhysDevMemoryPropsKHRNoICDSupport) {
1415 FrameworkEnvironment env{};
1416 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
1417 env.get_test_icd(0).physical_devices.push_back({});
1418
1419 InstWrapper instance(env.vulkan_functions);
1420 instance.create_info.add_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
1421 instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
1422
1423 PFN_vkGetPhysicalDeviceMemoryProperties2KHR GetPhysDevMemoryProps2KHR =
1424 instance.load("vkGetPhysicalDeviceMemoryProperties2KHR");
1425 ASSERT_EQ(GetPhysDevMemoryProps2KHR, nullptr);
1426 }
1427
1428 // Fill in random but valid data into the memory data struct for the current physical device
FillInRandomMemoryData(VkPhysicalDeviceMemoryProperties& props)1429 void FillInRandomMemoryData(VkPhysicalDeviceMemoryProperties& props) {
1430 props.memoryTypeCount = (rand() % 7) + 1;
1431 props.memoryHeapCount = (rand() % 7) + 1;
1432 for (uint32_t i = 0; i < props.memoryHeapCount; ++i) {
1433 props.memoryHeaps[i].size = (rand() % 728) + (rand() % 728) + 1;
1434 props.memoryHeaps[i].flags = (rand() % 2) + 1;
1435 }
1436 for (uint32_t i = 0; i < props.memoryTypeCount; ++i) {
1437 props.memoryTypes[i].propertyFlags = static_cast<VkMemoryPropertyFlags>((rand() % 2) + 1);
1438 props.memoryTypes[i].heapIndex = rand() % props.memoryHeapCount;
1439 }
1440 }
1441
1442 // Compare the memory structs
CompareMemoryData(const VkPhysicalDeviceMemoryProperties& props1, const VkPhysicalDeviceMemoryProperties2& props2)1443 bool CompareMemoryData(const VkPhysicalDeviceMemoryProperties& props1, const VkPhysicalDeviceMemoryProperties2& props2) {
1444 bool equal = true;
1445 equal = equal && props1.memoryTypeCount == props2.memoryProperties.memoryTypeCount;
1446 equal = equal && props1.memoryHeapCount == props2.memoryProperties.memoryHeapCount;
1447 for (uint32_t i = 0; i < props1.memoryHeapCount; ++i) {
1448 equal = equal && props1.memoryHeaps[i].size == props2.memoryProperties.memoryHeaps[i].size;
1449 equal = equal && props1.memoryHeaps[i].flags == props2.memoryProperties.memoryHeaps[i].flags;
1450 }
1451 for (uint32_t i = 0; i < props1.memoryTypeCount; ++i) {
1452 equal = equal && props1.memoryTypes[i].propertyFlags == props2.memoryProperties.memoryTypes[i].propertyFlags;
1453 equal = equal && props1.memoryTypes[i].heapIndex == props2.memoryProperties.memoryTypes[i].heapIndex;
1454 }
1455 return equal;
1456 }
1457
1458 // Test vkGetPhysicalDeviceMemoryProperties2KHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, PhysDevMemoryProps2KHRInstanceAndICDSupport)1459 TEST(LoaderInstPhysDevExts, PhysDevMemoryProps2KHRInstanceAndICDSupport) {
1460 FrameworkEnvironment env{};
1461 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
1462 env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
1463 env.get_test_icd(0).physical_devices.push_back({});
1464 FillInRandomMemoryData(env.get_test_icd(0).physical_devices.back().memory_properties);
1465
1466 InstWrapper instance(env.vulkan_functions);
1467 instance.create_info.add_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
1468 instance.CheckCreate();
1469
1470 PFN_vkGetPhysicalDeviceMemoryProperties2KHR GetPhysDevMemoryProps2KHR =
1471 instance.load("vkGetPhysicalDeviceMemoryProperties2KHR");
1472 ASSERT_NE(GetPhysDevMemoryProps2KHR, nullptr);
1473
1474 uint32_t driver_count = 1;
1475 VkPhysicalDevice physical_device;
1476 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
1477 ASSERT_EQ(driver_count, 1U);
1478
1479 VkPhysicalDeviceMemoryProperties props{};
1480 instance->vkGetPhysicalDeviceMemoryProperties(physical_device, &props);
1481
1482 VkPhysicalDeviceMemoryProperties2 props2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2};
1483 GetPhysDevMemoryProps2KHR(physical_device, &props2);
1484 ASSERT_TRUE(CompareMemoryData(props, props2));
1485 }
1486
1487 // Test vkGetPhysicalDeviceMemoryProperties2 where instance supports, an ICD, and a device under that ICD
1488 // also support, so everything should work and return properly.
1489 // Also check if the application didn't enable 1.1 and when a layer 'upgrades' the api version to 1.1
TEST(LoaderInstPhysDevExts, PhysDevMemoryProps2Simple)1490 TEST(LoaderInstPhysDevExts, PhysDevMemoryProps2Simple) {
1491 FrameworkEnvironment env{};
1492 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
1493 env.get_test_icd(0).icd_api_version = VK_API_VERSION_1_1;
1494 env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
1495 env.get_test_icd(0).physical_devices.push_back({});
1496 env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
1497 FillInRandomMemoryData(env.get_test_icd(0).physical_devices.back().memory_properties);
1498 {
1499 InstWrapper instance(env.vulkan_functions);
1500 instance.create_info.set_api_version(VK_API_VERSION_1_1);
1501 instance.CheckCreate();
1502
1503 PFN_vkGetPhysicalDeviceMemoryProperties2 GetPhysDevMemoryProps2 = instance.load("vkGetPhysicalDeviceMemoryProperties2");
1504 ASSERT_NE(GetPhysDevMemoryProps2, nullptr);
1505
1506 uint32_t driver_count = 1;
1507 VkPhysicalDevice physical_device;
1508 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
1509 ASSERT_EQ(driver_count, 1U);
1510
1511 VkPhysicalDeviceMemoryProperties props{};
1512 instance->vkGetPhysicalDeviceMemoryProperties(physical_device, &props);
1513
1514 VkPhysicalDeviceMemoryProperties2 props2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2};
1515 GetPhysDevMemoryProps2(physical_device, &props2);
1516 ASSERT_TRUE(CompareMemoryData(props, props2));
1517 }
1518 { // Now do the same logic but the application didn't enable 1.0 or the extension so they get the emulated call
1519 InstWrapper instance(env.vulkan_functions);
1520 instance.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
1521 instance.CheckCreate();
1522 DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
1523 CreateDebugUtilsMessenger(log);
1524
1525 PFN_vkGetPhysicalDeviceMemoryProperties2 GetPhysDevMemoryProps2 = instance.load("vkGetPhysicalDeviceMemoryProperties2");
1526 ASSERT_NE(GetPhysDevMemoryProps2, nullptr);
1527
1528 uint32_t driver_count = 1;
1529 VkPhysicalDevice physical_device;
1530 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
1531 ASSERT_EQ(driver_count, 1U);
1532
1533 VkPhysicalDeviceMemoryProperties props{};
1534 instance->vkGetPhysicalDeviceMemoryProperties(physical_device, &props);
1535
1536 VkPhysicalDeviceMemoryProperties2 props2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2};
1537 GetPhysDevMemoryProps2(physical_device, &props2);
1538 ASSERT_TRUE(CompareMemoryData(props, props2));
1539 ASSERT_TRUE(log.find("Emulating call in ICD"));
1540 }
1541 env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
1542 .set_name("modify_api_version_layer")
1543 .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
1544 .set_disable_environment("DisableEnvVar")),
1545 "modify_api_version_layer.json");
1546 env.get_test_layer().set_alter_api_version(VK_API_VERSION_1_1);
1547 { // Now do the same as above but with a layer that updates the version to 1.1 on behalf of the application
1548 InstWrapper instance(env.vulkan_functions);
1549 instance.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
1550 instance.CheckCreate();
1551 DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
1552 CreateDebugUtilsMessenger(log);
1553
1554 PFN_vkGetPhysicalDeviceMemoryProperties2 GetPhysDevMemoryProps2 = instance.load("vkGetPhysicalDeviceMemoryProperties2");
1555 ASSERT_NE(GetPhysDevMemoryProps2, nullptr);
1556
1557 uint32_t driver_count = 1;
1558 VkPhysicalDevice physical_device;
1559 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
1560 ASSERT_EQ(driver_count, 1U);
1561
1562 VkPhysicalDeviceMemoryProperties props{};
1563 instance->vkGetPhysicalDeviceMemoryProperties(physical_device, &props);
1564
1565 VkPhysicalDeviceMemoryProperties2 props2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2};
1566 GetPhysDevMemoryProps2(physical_device, &props2);
1567 ASSERT_TRUE(CompareMemoryData(props, props2));
1568 ASSERT_FALSE(log.find("Emulating call in ICD"));
1569 }
1570 }
1571
1572 // Test vkGetPhysicalDeviceMemoryProperties2 and vkGetPhysicalDeviceMemoryProperties2KHR where ICD is 1.0 and supports
1573 // extension but the instance supports 1.1 and the extension
TEST(LoaderInstPhysDevExts, PhysDevMemoryProps2KHRInstanceSupports11)1574 TEST(LoaderInstPhysDevExts, PhysDevMemoryProps2KHRInstanceSupports11) {
1575 FrameworkEnvironment env{};
1576 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
1577 env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
1578 env.get_test_icd(0).physical_devices.push_back({});
1579 env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
1580 FillInRandomMemoryData(env.get_test_icd(0).physical_devices.back().memory_properties);
1581
1582 InstWrapper instance(env.vulkan_functions);
1583 instance.create_info.set_api_version(VK_API_VERSION_1_1);
1584 instance.create_info.add_extensions(
1585 {VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_EXTENSION_NAME});
1586 instance.CheckCreate();
1587 DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
1588 CreateDebugUtilsMessenger(log);
1589
1590 PFN_vkGetPhysicalDeviceMemoryProperties2 GetPhysDevMemoryProps2 = instance.load("vkGetPhysicalDeviceMemoryProperties2");
1591 ASSERT_NE(GetPhysDevMemoryProps2, nullptr);
1592
1593 PFN_vkGetPhysicalDeviceMemoryProperties2KHR GetPhysDevMemoryProps2KHR =
1594 instance.load("vkGetPhysicalDeviceMemoryProperties2KHR");
1595 ASSERT_NE(GetPhysDevMemoryProps2KHR, nullptr);
1596
1597 uint32_t driver_count = 1;
1598 VkPhysicalDevice physical_device;
1599 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
1600 ASSERT_EQ(driver_count, 1U);
1601
1602 VkPhysicalDeviceMemoryProperties props{};
1603 instance->vkGetPhysicalDeviceMemoryProperties(physical_device, &props);
1604
1605 VkPhysicalDeviceMemoryProperties2 props2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2};
1606 GetPhysDevMemoryProps2(physical_device, &props2);
1607 ASSERT_TRUE(CompareMemoryData(props, props2));
1608
1609 VkPhysicalDeviceMemoryProperties2KHR props2KHR{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR};
1610 GetPhysDevMemoryProps2KHR(physical_device, &props2KHR);
1611 ASSERT_TRUE(CompareMemoryData(props, props2KHR));
1612
1613 ASSERT_FALSE(log.find("Emulating call in ICD"));
1614 }
1615 // Test vkGetPhysicalDeviceMemoryProperties2 where instance supports it with some ICDs that both support
1616 // and don't support it:
1617 // ICD 0 supports
1618 // Physical device 0 does not
1619 // Physical device 1 does
1620 // Physical device 2 does not
1621 // ICD 1 doesn't support
1622 // Physical device 3 does not
1623 // ICD 2 supports
1624 // Physical device 4 does not
1625 // Physical device 5 does not
1626 // ICD 3 supports
1627 // Physical device 6 does
TEST(LoaderInstPhysDevExts, PhysDevMemoryPropsMixed)1628 TEST(LoaderInstPhysDevExts, PhysDevMemoryPropsMixed) {
1629 FrameworkEnvironment env{};
1630 const uint32_t max_icd_count = 4;
1631 const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
1632 const uint32_t max_phys_devs = 7;
1633
1634 for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
1635 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, icd != 1 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0));
1636 auto& cur_icd = env.get_test_icd(icd);
1637
1638 // ICD 1 should not have 1.1
1639 if (icd != 1) {
1640 cur_icd.icd_api_version = VK_API_VERSION_1_1;
1641 cur_icd.add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
1642 }
1643
1644 uint32_t rand_vendor_id;
1645 uint32_t rand_driver_vers;
1646 FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
1647
1648 for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
1649 uint32_t device_version = VK_API_VERSION_1_0;
1650 cur_icd.physical_devices.push_back({});
1651 auto& cur_dev = cur_icd.physical_devices.back();
1652
1653 // 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
1654 if ((icd == 0 && dev == 1) || icd == 3) {
1655 cur_dev.extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
1656 device_version = VK_API_VERSION_1_1;
1657 }
1658
1659 // Still set physical device properties (so we can determine if device is correct API version)
1660 FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
1661 FillInRandomMemoryData(cur_dev.memory_properties);
1662 }
1663 }
1664
1665 InstWrapper instance(env.vulkan_functions);
1666 instance.create_info.set_api_version(VK_API_VERSION_1_1);
1667 instance.CheckCreate();
1668
1669 PFN_vkGetPhysicalDeviceMemoryProperties2 GetPhysDevMemoryProps2 = instance.load("vkGetPhysicalDeviceMemoryProperties2");
1670 ASSERT_NE(GetPhysDevMemoryProps2, nullptr);
1671
1672 uint32_t device_count = max_phys_devs;
1673 std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
1674 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
1675 ASSERT_EQ(device_count, max_phys_devs);
1676
1677 for (uint32_t dev = 0; dev < device_count; ++dev) {
1678 VkPhysicalDeviceMemoryProperties props{};
1679 instance->vkGetPhysicalDeviceMemoryProperties(physical_devices[dev], &props);
1680
1681 VkPhysicalDeviceMemoryProperties2 props2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2};
1682 GetPhysDevMemoryProps2(physical_devices[dev], &props2);
1683 ASSERT_TRUE(CompareMemoryData(props, props2));
1684 }
1685 }
1686
1687 // Test vkGetPhysicalDeviceQueueFamilyProperties2KHR where nothing supports it.
TEST(LoaderInstPhysDevExts, PhysDevQueueFamilyProps2KHRNoSupport)1688 TEST(LoaderInstPhysDevExts, PhysDevQueueFamilyProps2KHRNoSupport) {
1689 FrameworkEnvironment env{};
1690 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
1691 env.get_test_icd(0).physical_devices.push_back({});
1692
1693 InstWrapper instance(env.vulkan_functions);
1694 instance.CheckCreate();
1695
1696 PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR GetPhysDevQueueFamilyProps2KHR =
1697 instance.load("vkGetPhysicalDeviceQueueFamilyProperties2KHR");
1698 ASSERT_EQ(GetPhysDevQueueFamilyProps2KHR, nullptr);
1699 }
1700
1701 // Test vkGetPhysicalDeviceQueueFamilyProperties2KHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevQueueFamilyPropsKHRNoICDSupport)1702 TEST(LoaderInstPhysDevExts, PhysDevQueueFamilyPropsKHRNoICDSupport) {
1703 FrameworkEnvironment env{};
1704 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
1705 env.get_test_icd(0).physical_devices.push_back({});
1706
1707 InstWrapper instance(env.vulkan_functions);
1708 instance.create_info.add_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
1709 instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
1710
1711 PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR GetPhysDevQueueFamilyProps2KHR =
1712 instance.load("vkGetPhysicalDeviceQueueFamilyProperties2KHR");
1713 ASSERT_EQ(GetPhysDevQueueFamilyProps2KHR, nullptr);
1714 }
1715
1716 // Fill in random but valid data into the queue family data struct for the current physical device
FillInRandomQueueFamilyData(std::vector<MockQueueFamilyProperties>& props)1717 uint32_t FillInRandomQueueFamilyData(std::vector<MockQueueFamilyProperties>& props) {
1718 props.resize((rand() % 4) + 1);
1719 for (uint32_t i = 0; i < props.size(); ++i) {
1720 props[i].properties.queueFlags = (rand() % 30) + 1;
1721 props[i].properties.queueCount = (rand() % 7) + 1;
1722 props[i].properties.timestampValidBits = (rand() % 30) + 7;
1723 props[i].properties.minImageTransferGranularity.width = (rand() % 30) + 1;
1724 props[i].properties.minImageTransferGranularity.height = (rand() % 30) + 1;
1725 props[i].properties.minImageTransferGranularity.depth = (rand() % 30) + 1;
1726 props[i].support_present = rand() % 2 == 0;
1727 }
1728 return static_cast<uint32_t>(props.size());
1729 }
1730
1731 // Compare the queue family structs
CompareQueueFamilyData(const std::vector<VkQueueFamilyProperties>& props1, const std::vector<VkQueueFamilyProperties2>& props2)1732 bool CompareQueueFamilyData(const std::vector<VkQueueFamilyProperties>& props1,
1733 const std::vector<VkQueueFamilyProperties2>& props2) {
1734 if (props1.size() != props2.size()) return false;
1735 bool equal = true;
1736 for (uint32_t i = 0; i < props1.size(); ++i) {
1737 equal = equal && props1[i].queueFlags == props2[i].queueFamilyProperties.queueFlags;
1738 equal = equal && props1[i].queueCount == props2[i].queueFamilyProperties.queueCount;
1739 equal = equal && props1[i].timestampValidBits == props2[i].queueFamilyProperties.timestampValidBits;
1740 equal = equal &&
1741 props1[i].minImageTransferGranularity.width == props2[i].queueFamilyProperties.minImageTransferGranularity.width;
1742 equal = equal &&
1743 props1[i].minImageTransferGranularity.height == props2[i].queueFamilyProperties.minImageTransferGranularity.height;
1744 equal = equal &&
1745 props1[i].minImageTransferGranularity.depth == props2[i].queueFamilyProperties.minImageTransferGranularity.depth;
1746 }
1747 return equal;
1748 }
1749
1750 // Test vkGetPhysicalDeviceQueueFamilyProperties2KHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, PhysDevQueueFamilyProps2KHRInstanceAndICDSupport)1751 TEST(LoaderInstPhysDevExts, PhysDevQueueFamilyProps2KHRInstanceAndICDSupport) {
1752 FrameworkEnvironment env{};
1753 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
1754 env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
1755 env.get_test_icd(0).physical_devices.push_back({});
1756 uint32_t num_fam = FillInRandomQueueFamilyData(env.get_test_icd(0).physical_devices.back().queue_family_properties);
1757
1758 InstWrapper instance(env.vulkan_functions);
1759 instance.create_info.add_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
1760 instance.CheckCreate();
1761
1762 PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR GetPhysDevQueueFamilyProps2KHR =
1763 instance.load("vkGetPhysicalDeviceQueueFamilyProperties2KHR");
1764 ASSERT_NE(GetPhysDevQueueFamilyProps2KHR, nullptr);
1765
1766 uint32_t driver_count = 1;
1767 VkPhysicalDevice physical_device;
1768 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
1769 ASSERT_EQ(driver_count, 1U);
1770
1771 uint32_t ret_fam_1 = 0;
1772 std::vector<VkQueueFamilyProperties> props{};
1773 instance->vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &ret_fam_1, nullptr);
1774 ASSERT_EQ(num_fam, ret_fam_1);
1775 props.resize(ret_fam_1);
1776
1777 instance->vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &ret_fam_1, props.data());
1778
1779 std::vector<VkQueueFamilyProperties2> props2{};
1780 uint32_t ret_fam_2 = 0;
1781 GetPhysDevQueueFamilyProps2KHR(physical_device, &ret_fam_2, nullptr);
1782 ASSERT_EQ(ret_fam_1, ret_fam_2);
1783 props2.resize(ret_fam_2, VkQueueFamilyProperties2{VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2});
1784 GetPhysDevQueueFamilyProps2KHR(physical_device, &ret_fam_2, props2.data());
1785 ASSERT_TRUE(CompareQueueFamilyData(props, props2));
1786 }
1787
1788 // Test vkGetPhysicalDeviceQueueFamilyProperties2 where instance supports, an ICD, and a device under that ICD
1789 // also support, so everything should work and return properly.
1790 // Also check if the application didn't enable 1.1 and when a layer 'upgrades' the api version to 1.1
TEST(LoaderInstPhysDevExts, PhysDevQueueFamilyProps2Simple)1791 TEST(LoaderInstPhysDevExts, PhysDevQueueFamilyProps2Simple) {
1792 FrameworkEnvironment env{};
1793 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
1794 env.get_test_icd(0).icd_api_version = VK_API_VERSION_1_1;
1795 env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
1796 env.get_test_icd(0).physical_devices.push_back({});
1797 env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
1798 uint32_t num_fam = FillInRandomQueueFamilyData(env.get_test_icd(0).physical_devices.back().queue_family_properties);
1799 {
1800 InstWrapper instance(env.vulkan_functions);
1801 instance.create_info.set_api_version(VK_API_VERSION_1_1);
1802 instance.CheckCreate();
1803
1804 PFN_vkGetPhysicalDeviceQueueFamilyProperties2 GetPhysDevQueueFamilyProps2 =
1805 instance.load("vkGetPhysicalDeviceQueueFamilyProperties2");
1806 ASSERT_NE(GetPhysDevQueueFamilyProps2, nullptr);
1807
1808 uint32_t driver_count = 1;
1809 VkPhysicalDevice physical_device;
1810 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
1811 ASSERT_EQ(driver_count, 1U);
1812
1813 uint32_t ret_fam_1 = 0;
1814 std::vector<VkQueueFamilyProperties> props{};
1815 instance->vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &ret_fam_1, nullptr);
1816 ASSERT_EQ(num_fam, ret_fam_1);
1817 props.resize(ret_fam_1);
1818
1819 instance->vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &ret_fam_1, props.data());
1820
1821 std::vector<VkQueueFamilyProperties2> props2{};
1822 uint32_t ret_fam_2 = 0;
1823 GetPhysDevQueueFamilyProps2(physical_device, &ret_fam_2, nullptr);
1824 ASSERT_EQ(ret_fam_1, ret_fam_2);
1825 props2.resize(ret_fam_2, VkQueueFamilyProperties2{VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2});
1826 GetPhysDevQueueFamilyProps2(physical_device, &ret_fam_2, props2.data());
1827 ASSERT_TRUE(CompareQueueFamilyData(props, props2));
1828 }
1829 { // Now do the same logic but the application didn't enable 1.0 or the extension so they get the emulated call
1830 InstWrapper instance(env.vulkan_functions);
1831 instance.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
1832 instance.CheckCreate();
1833 DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
1834 CreateDebugUtilsMessenger(log);
1835
1836 PFN_vkGetPhysicalDeviceQueueFamilyProperties2 GetPhysDevQueueFamilyProps2 =
1837 instance.load("vkGetPhysicalDeviceQueueFamilyProperties2");
1838 ASSERT_NE(GetPhysDevQueueFamilyProps2, nullptr);
1839
1840 uint32_t driver_count = 1;
1841 VkPhysicalDevice physical_device;
1842 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
1843 ASSERT_EQ(driver_count, 1U);
1844
1845 uint32_t ret_fam_1 = 0;
1846 std::vector<VkQueueFamilyProperties> props{};
1847 instance->vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &ret_fam_1, nullptr);
1848 ASSERT_EQ(num_fam, ret_fam_1);
1849 props.resize(ret_fam_1);
1850
1851 instance->vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &ret_fam_1, props.data());
1852
1853 std::vector<VkQueueFamilyProperties2> props2{};
1854 uint32_t ret_fam_2 = 0;
1855 GetPhysDevQueueFamilyProps2(physical_device, &ret_fam_2, nullptr);
1856 ASSERT_EQ(ret_fam_1, ret_fam_2);
1857 props2.resize(ret_fam_2, VkQueueFamilyProperties2{VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2});
1858 GetPhysDevQueueFamilyProps2(physical_device, &ret_fam_2, props2.data());
1859 ASSERT_TRUE(CompareQueueFamilyData(props, props2));
1860 ASSERT_TRUE(log.find("Emulating call in ICD"));
1861 }
1862 env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
1863 .set_name("modify_api_version_layer")
1864 .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
1865 .set_disable_environment("DisableEnvVar")),
1866 "modify_api_version_layer.json");
1867 env.get_test_layer().set_alter_api_version(VK_API_VERSION_1_1);
1868 { // Now do the same as above but with a layer that updates the version to 1.1 on behalf of the application
1869 InstWrapper instance(env.vulkan_functions);
1870 instance.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
1871 instance.CheckCreate();
1872 DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
1873 CreateDebugUtilsMessenger(log);
1874
1875 PFN_vkGetPhysicalDeviceQueueFamilyProperties2 GetPhysDevQueueFamilyProps2 =
1876 instance.load("vkGetPhysicalDeviceQueueFamilyProperties2");
1877 ASSERT_NE(GetPhysDevQueueFamilyProps2, nullptr);
1878
1879 uint32_t driver_count = 1;
1880 VkPhysicalDevice physical_device;
1881 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
1882 ASSERT_EQ(driver_count, 1U);
1883
1884 uint32_t ret_fam_1 = 0;
1885 std::vector<VkQueueFamilyProperties> props{};
1886 instance->vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &ret_fam_1, nullptr);
1887 ASSERT_EQ(num_fam, ret_fam_1);
1888 props.resize(ret_fam_1);
1889
1890 instance->vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &ret_fam_1, props.data());
1891
1892 std::vector<VkQueueFamilyProperties2> props2{};
1893 uint32_t ret_fam_2 = 0;
1894 GetPhysDevQueueFamilyProps2(physical_device, &ret_fam_2, nullptr);
1895 ASSERT_EQ(ret_fam_1, ret_fam_2);
1896 props2.resize(ret_fam_2, VkQueueFamilyProperties2{VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2});
1897 GetPhysDevQueueFamilyProps2(physical_device, &ret_fam_2, props2.data());
1898 ASSERT_TRUE(CompareQueueFamilyData(props, props2));
1899 ASSERT_FALSE(log.find("Emulating call in ICD"));
1900 }
1901 }
1902
1903 // Test vkGetPhysicalDeviceQueueFamilyProperties2 and vkGetPhysicalDeviceQueueFamilyProperties2KHR where ICD is 1.0 and supports
1904 // extension but the instance supports 1.1 and the extension
TEST(LoaderInstPhysDevExts, PhysDevQueueFamilyProps2KHRInstanceSupports11)1905 TEST(LoaderInstPhysDevExts, PhysDevQueueFamilyProps2KHRInstanceSupports11) {
1906 FrameworkEnvironment env{};
1907 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
1908 env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
1909 env.get_test_icd(0).physical_devices.push_back({});
1910 env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
1911 uint32_t num_fam = FillInRandomQueueFamilyData(env.get_test_icd(0).physical_devices.back().queue_family_properties);
1912
1913 InstWrapper instance(env.vulkan_functions);
1914 instance.create_info.set_api_version(VK_API_VERSION_1_1);
1915 instance.create_info.add_extensions(
1916 {VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_EXTENSION_NAME});
1917 instance.CheckCreate();
1918 DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
1919 CreateDebugUtilsMessenger(log);
1920
1921 PFN_vkGetPhysicalDeviceQueueFamilyProperties2 GetPhysDevQueueFamilyProps2 =
1922 instance.load("vkGetPhysicalDeviceQueueFamilyProperties2");
1923 ASSERT_NE(GetPhysDevQueueFamilyProps2, nullptr);
1924
1925 PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR GetPhysDevQueueFamilyProps2KHR =
1926 instance.load("vkGetPhysicalDeviceQueueFamilyProperties2KHR");
1927 ASSERT_NE(GetPhysDevQueueFamilyProps2KHR, nullptr);
1928
1929 uint32_t driver_count = 1;
1930 VkPhysicalDevice physical_device;
1931 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
1932 ASSERT_EQ(driver_count, 1U);
1933
1934 uint32_t ret_fam_1 = 0;
1935 std::vector<VkQueueFamilyProperties> props{};
1936 instance->vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &ret_fam_1, nullptr);
1937 ASSERT_EQ(num_fam, ret_fam_1);
1938 props.resize(ret_fam_1);
1939
1940 instance->vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &ret_fam_1, props.data());
1941
1942 std::vector<VkQueueFamilyProperties2> props2{};
1943 uint32_t ret_fam_2 = 0;
1944 GetPhysDevQueueFamilyProps2(physical_device, &ret_fam_2, nullptr);
1945 ASSERT_EQ(ret_fam_1, ret_fam_2);
1946 props2.resize(ret_fam_2, VkQueueFamilyProperties2{VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2});
1947 GetPhysDevQueueFamilyProps2(physical_device, &ret_fam_2, props2.data());
1948 ASSERT_TRUE(CompareQueueFamilyData(props, props2));
1949
1950 std::vector<VkQueueFamilyProperties2KHR> props2KHR{};
1951 uint32_t ret_fam_2_khr = 0;
1952 GetPhysDevQueueFamilyProps2KHR(physical_device, &ret_fam_2_khr, nullptr);
1953 ASSERT_EQ(ret_fam_1, ret_fam_2_khr);
1954 props2KHR.resize(ret_fam_2_khr, VkQueueFamilyProperties2KHR{VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR});
1955 GetPhysDevQueueFamilyProps2KHR(physical_device, &ret_fam_2_khr, props2KHR.data());
1956 ASSERT_TRUE(CompareQueueFamilyData(props, props2KHR));
1957
1958 ASSERT_FALSE(log.find("Emulating call in ICD"));
1959 }
1960
1961 // Test vkGetPhysicalDeviceQueueFamilyProperties2 where instance supports it with some ICDs that both support
1962 // and don't support it:
1963 // ICD 0 supports
1964 // Physical device 0 does not
1965 // Physical device 1 does
1966 // Physical device 2 does not
1967 // ICD 1 doesn't support
1968 // Physical device 3 does not
1969 // ICD 2 supports
1970 // Physical device 4 does not
1971 // Physical device 5 does not
1972 // ICD 3 supports
1973 // Physical device 6 does
TEST(LoaderInstPhysDevExts, PhysDevQueueFamilyPropsMixed)1974 TEST(LoaderInstPhysDevExts, PhysDevQueueFamilyPropsMixed) {
1975 FrameworkEnvironment env{};
1976 const uint32_t max_icd_count = 4;
1977 const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
1978 const uint32_t max_phys_devs = 7;
1979
1980 for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
1981 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, icd != 1 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0));
1982 auto& cur_icd = env.get_test_icd(icd);
1983
1984 // ICD 1 should not have 1.1
1985 if (icd != 1) {
1986 cur_icd.icd_api_version = VK_API_VERSION_1_1;
1987 cur_icd.add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
1988 }
1989
1990 uint32_t rand_vendor_id;
1991 uint32_t rand_driver_vers;
1992 FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
1993
1994 for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
1995 uint32_t device_version = VK_API_VERSION_1_0;
1996 cur_icd.physical_devices.push_back({});
1997 auto& cur_dev = cur_icd.physical_devices.back();
1998
1999 // 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
2000 if ((icd == 0 && dev == 1) || icd == 3) {
2001 cur_dev.extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
2002 device_version = VK_API_VERSION_1_1;
2003 }
2004
2005 // Still set physical device properties (so we can determine if device is correct API version)
2006 FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
2007 FillInRandomQueueFamilyData(cur_dev.queue_family_properties);
2008 }
2009 }
2010
2011 InstWrapper instance(env.vulkan_functions);
2012 instance.create_info.set_api_version(VK_API_VERSION_1_1);
2013 instance.CheckCreate();
2014
2015 PFN_vkGetPhysicalDeviceQueueFamilyProperties2 GetPhysDevQueueFamilyProps2 =
2016 instance.load("vkGetPhysicalDeviceQueueFamilyProperties2");
2017 ASSERT_NE(GetPhysDevQueueFamilyProps2, nullptr);
2018
2019 uint32_t device_count = max_phys_devs;
2020 std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
2021 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
2022 ASSERT_EQ(device_count, max_phys_devs);
2023
2024 for (uint32_t dev = 0; dev < device_count; ++dev) {
2025 uint32_t ret_fam_1 = 0;
2026 std::vector<VkQueueFamilyProperties> props{};
2027 instance->vkGetPhysicalDeviceQueueFamilyProperties(physical_devices[dev], &ret_fam_1, nullptr);
2028 props.resize(ret_fam_1);
2029 instance->vkGetPhysicalDeviceQueueFamilyProperties(physical_devices[dev], &ret_fam_1, props.data());
2030
2031 std::vector<VkQueueFamilyProperties2> props2{};
2032 uint32_t ret_fam_2 = 0;
2033 GetPhysDevQueueFamilyProps2(physical_devices[dev], &ret_fam_2, nullptr);
2034 ASSERT_EQ(ret_fam_1, ret_fam_2);
2035 props2.resize(ret_fam_2, VkQueueFamilyProperties2{VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2});
2036 GetPhysDevQueueFamilyProps2(physical_devices[dev], &ret_fam_2, props2.data());
2037 ASSERT_TRUE(CompareQueueFamilyData(props, props2));
2038 }
2039 }
2040
2041 // Test vkGetPhysicalDeviceSparseImageFormatProperties2KHR where nothing supports it.
TEST(LoaderInstPhysDevExts, PhysDevSparseImageFormatProps2KHRNoSupport)2042 TEST(LoaderInstPhysDevExts, PhysDevSparseImageFormatProps2KHRNoSupport) {
2043 FrameworkEnvironment env{};
2044 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
2045 env.get_test_icd(0).physical_devices.push_back({});
2046
2047 InstWrapper instance(env.vulkan_functions);
2048 instance.CheckCreate();
2049
2050 PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR GetPhysDevSparseImageFormatProps2KHR =
2051 instance.load("vkGetPhysicalDeviceSparseImageFormatProperties2KHR");
2052 ASSERT_EQ(GetPhysDevSparseImageFormatProps2KHR, nullptr);
2053 }
2054
2055 // Test vkGetPhysicalDeviceSparseImageFormatProperties2KHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevSparseImageFormatPropsKHRNoICDSupport)2056 TEST(LoaderInstPhysDevExts, PhysDevSparseImageFormatPropsKHRNoICDSupport) {
2057 FrameworkEnvironment env{};
2058 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
2059 env.get_test_icd(0).physical_devices.push_back({});
2060
2061 InstWrapper instance(env.vulkan_functions);
2062 instance.create_info.add_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
2063 instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
2064
2065 PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR GetPhysDevSparseImageFormatProps2KHR =
2066 instance.load("vkGetPhysicalDeviceSparseImageFormatProperties2KHR");
2067 ASSERT_EQ(GetPhysDevSparseImageFormatProps2KHR, nullptr);
2068 }
2069
2070 // Fill in random but valid data into the sparse image format data struct for the current physical device
FillInRandomSparseImageFormatData(std::vector<VkSparseImageFormatProperties>& props)2071 void FillInRandomSparseImageFormatData(std::vector<VkSparseImageFormatProperties>& props) {
2072 props.resize((rand() % 4) + 1);
2073 for (uint32_t i = 0; i < props.size(); ++i) {
2074 props[i].aspectMask = static_cast<VkImageAspectFlags>((rand() % 0x7FE) + 1);
2075 props[i].imageGranularity = {static_cast<uint32_t>(rand() % 512), static_cast<uint32_t>(rand() % 512),
2076 static_cast<uint32_t>(rand() % 512)};
2077 props[i].flags = static_cast<VkSparseImageFormatFlags>((rand() % 6) + 1);
2078 }
2079 }
2080
2081 // Compare the sparse image format structs
CompareSparseImageFormatData(const std::vector<VkSparseImageFormatProperties>& props1, const std::vector<VkSparseImageFormatProperties2>& props2)2082 bool CompareSparseImageFormatData(const std::vector<VkSparseImageFormatProperties>& props1,
2083 const std::vector<VkSparseImageFormatProperties2>& props2) {
2084 if (props1.size() != props2.size()) return false;
2085 bool equal = true;
2086 for (uint32_t i = 0; i < props1.size(); ++i) {
2087 equal = equal && props1[i].aspectMask == props2[i].properties.aspectMask;
2088 equal = equal && props1[i].imageGranularity.width == props2[i].properties.imageGranularity.width;
2089 equal = equal && props1[i].imageGranularity.height == props2[i].properties.imageGranularity.height;
2090 equal = equal && props1[i].imageGranularity.depth == props2[i].properties.imageGranularity.depth;
2091 equal = equal && props1[i].flags == props2[i].properties.flags;
2092 }
2093 return equal;
2094 }
2095
2096 // Test vkGetPhysicalDeviceSparseImageFormatProperties2KHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, PhysDevSparseImageFormatProps2KHRInstanceAndICDSupport)2097 TEST(LoaderInstPhysDevExts, PhysDevSparseImageFormatProps2KHRInstanceAndICDSupport) {
2098 FrameworkEnvironment env{};
2099 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
2100 env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
2101 env.get_test_icd(0).physical_devices.push_back({});
2102 FillInRandomSparseImageFormatData(env.get_test_icd(0).physical_devices.back().sparse_image_format_properties);
2103
2104 InstWrapper instance(env.vulkan_functions);
2105 instance.create_info.add_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
2106 instance.CheckCreate();
2107
2108 PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR GetPhysDevSparseImageFormatProps2KHR =
2109 instance.load("vkGetPhysicalDeviceSparseImageFormatProperties2KHR");
2110 ASSERT_NE(GetPhysDevSparseImageFormatProps2KHR, nullptr);
2111
2112 uint32_t driver_count = 1;
2113 VkPhysicalDevice physical_device;
2114 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
2115 ASSERT_EQ(driver_count, 1U);
2116
2117 std::vector<VkSparseImageFormatProperties> props{};
2118 uint32_t sparse_count_1 = 0;
2119 instance->vkGetPhysicalDeviceSparseImageFormatProperties(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, VK_IMAGE_TYPE_2D,
2120 VK_SAMPLE_COUNT_4_BIT, VK_IMAGE_USAGE_STORAGE_BIT,
2121 VK_IMAGE_TILING_OPTIMAL, &sparse_count_1, nullptr);
2122 ASSERT_NE(sparse_count_1, 0U);
2123 props.resize(sparse_count_1);
2124 instance->vkGetPhysicalDeviceSparseImageFormatProperties(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, VK_IMAGE_TYPE_2D,
2125 VK_SAMPLE_COUNT_4_BIT, VK_IMAGE_USAGE_STORAGE_BIT,
2126 VK_IMAGE_TILING_OPTIMAL, &sparse_count_1, props.data());
2127 ASSERT_NE(sparse_count_1, 0U);
2128
2129 VkPhysicalDeviceSparseImageFormatInfo2 info2{
2130 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2, // sType
2131 nullptr, // pNext
2132 VK_FORMAT_R4G4_UNORM_PACK8, // format
2133 VK_IMAGE_TYPE_2D, // type
2134 VK_SAMPLE_COUNT_4_BIT, // samples
2135 VK_IMAGE_USAGE_STORAGE_BIT, // usage
2136 VK_IMAGE_TILING_OPTIMAL, // tiling
2137 };
2138 std::vector<VkSparseImageFormatProperties2> props2{};
2139 uint32_t sparse_count_2 = 0;
2140 GetPhysDevSparseImageFormatProps2KHR(physical_device, &info2, &sparse_count_2, nullptr);
2141 ASSERT_EQ(sparse_count_1, sparse_count_2);
2142 props2.resize(sparse_count_2, VkSparseImageFormatProperties2{VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2});
2143 GetPhysDevSparseImageFormatProps2KHR(physical_device, &info2, &sparse_count_2, props2.data());
2144 ASSERT_EQ(sparse_count_1, sparse_count_2);
2145 ASSERT_TRUE(CompareSparseImageFormatData(props, props2));
2146 }
2147
2148 // Test vkGetPhysicalDeviceSparseImageFormatProperties2 where instance supports, an ICD, and a device under that ICD
2149 // also support, so everything should work and return properly.
2150 // Also check if the application didn't enable 1.1 and when a layer 'upgrades' the api version to 1.1
TEST(LoaderInstPhysDevExts, PhysDevSparseImageFormatProps2Simple)2151 TEST(LoaderInstPhysDevExts, PhysDevSparseImageFormatProps2Simple) {
2152 FrameworkEnvironment env{};
2153 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
2154 env.get_test_icd(0).icd_api_version = VK_API_VERSION_1_1;
2155 env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
2156 env.get_test_icd(0).physical_devices.push_back({});
2157 env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
2158 FillInRandomSparseImageFormatData(env.get_test_icd(0).physical_devices.back().sparse_image_format_properties);
2159 {
2160 InstWrapper instance(env.vulkan_functions);
2161 instance.create_info.set_api_version(VK_API_VERSION_1_1);
2162 instance.CheckCreate();
2163
2164 PFN_vkGetPhysicalDeviceSparseImageFormatProperties2 GetPhysDevSparseImageFormatProps2 =
2165 instance.load("vkGetPhysicalDeviceSparseImageFormatProperties2");
2166 ASSERT_NE(GetPhysDevSparseImageFormatProps2, nullptr);
2167
2168 uint32_t driver_count = 1;
2169 VkPhysicalDevice physical_device;
2170 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
2171 ASSERT_EQ(driver_count, 1U);
2172
2173 std::vector<VkSparseImageFormatProperties> props{};
2174 uint32_t sparse_count_1 = 0;
2175 instance->vkGetPhysicalDeviceSparseImageFormatProperties(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, VK_IMAGE_TYPE_2D,
2176 VK_SAMPLE_COUNT_4_BIT, VK_IMAGE_USAGE_STORAGE_BIT,
2177 VK_IMAGE_TILING_OPTIMAL, &sparse_count_1, nullptr);
2178 ASSERT_NE(sparse_count_1, 0U);
2179 props.resize(sparse_count_1);
2180 instance->vkGetPhysicalDeviceSparseImageFormatProperties(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, VK_IMAGE_TYPE_2D,
2181 VK_SAMPLE_COUNT_4_BIT, VK_IMAGE_USAGE_STORAGE_BIT,
2182 VK_IMAGE_TILING_OPTIMAL, &sparse_count_1, props.data());
2183 ASSERT_NE(sparse_count_1, 0U);
2184
2185 VkPhysicalDeviceSparseImageFormatInfo2 info2{
2186 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2, // sType
2187 nullptr, // pNext
2188 VK_FORMAT_R4G4_UNORM_PACK8, // format
2189 VK_IMAGE_TYPE_2D, // type
2190 VK_SAMPLE_COUNT_4_BIT, // samples
2191 VK_IMAGE_USAGE_STORAGE_BIT, // usage
2192 VK_IMAGE_TILING_OPTIMAL, // tiling
2193 };
2194 std::vector<VkSparseImageFormatProperties2> props2{};
2195 uint32_t sparse_count_2 = 0;
2196 GetPhysDevSparseImageFormatProps2(physical_device, &info2, &sparse_count_2, nullptr);
2197 ASSERT_EQ(sparse_count_1, sparse_count_2);
2198 props2.resize(sparse_count_2, VkSparseImageFormatProperties2{VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2});
2199 GetPhysDevSparseImageFormatProps2(physical_device, &info2, &sparse_count_2, props2.data());
2200 ASSERT_EQ(sparse_count_1, sparse_count_2);
2201 ASSERT_TRUE(CompareSparseImageFormatData(props, props2));
2202 }
2203 { // Now do the same logic but the application didn't enable 1.0 or the extension so they get the emulated call
2204 InstWrapper instance(env.vulkan_functions);
2205 instance.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
2206 instance.CheckCreate();
2207 DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
2208 CreateDebugUtilsMessenger(log);
2209
2210 PFN_vkGetPhysicalDeviceSparseImageFormatProperties2 GetPhysDevSparseImageFormatProps2 =
2211 instance.load("vkGetPhysicalDeviceSparseImageFormatProperties2");
2212 ASSERT_NE(GetPhysDevSparseImageFormatProps2, nullptr);
2213
2214 uint32_t driver_count = 1;
2215 VkPhysicalDevice physical_device;
2216 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
2217 ASSERT_EQ(driver_count, 1U);
2218
2219 std::vector<VkSparseImageFormatProperties> props{};
2220 uint32_t sparse_count_1 = 0;
2221 instance->vkGetPhysicalDeviceSparseImageFormatProperties(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, VK_IMAGE_TYPE_2D,
2222 VK_SAMPLE_COUNT_4_BIT, VK_IMAGE_USAGE_STORAGE_BIT,
2223 VK_IMAGE_TILING_OPTIMAL, &sparse_count_1, nullptr);
2224 ASSERT_NE(sparse_count_1, 0U);
2225 props.resize(sparse_count_1);
2226 instance->vkGetPhysicalDeviceSparseImageFormatProperties(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, VK_IMAGE_TYPE_2D,
2227 VK_SAMPLE_COUNT_4_BIT, VK_IMAGE_USAGE_STORAGE_BIT,
2228 VK_IMAGE_TILING_OPTIMAL, &sparse_count_1, props.data());
2229 ASSERT_NE(sparse_count_1, 0U);
2230
2231 VkPhysicalDeviceSparseImageFormatInfo2 info2{
2232 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2, // sType
2233 nullptr, // pNext
2234 VK_FORMAT_R4G4_UNORM_PACK8, // format
2235 VK_IMAGE_TYPE_2D, // type
2236 VK_SAMPLE_COUNT_4_BIT, // samples
2237 VK_IMAGE_USAGE_STORAGE_BIT, // usage
2238 VK_IMAGE_TILING_OPTIMAL, // tiling
2239 };
2240 std::vector<VkSparseImageFormatProperties2> props2{};
2241 uint32_t sparse_count_2 = 0;
2242 GetPhysDevSparseImageFormatProps2(physical_device, &info2, &sparse_count_2, nullptr);
2243 ASSERT_EQ(sparse_count_1, sparse_count_2);
2244 props2.resize(sparse_count_2, VkSparseImageFormatProperties2{VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2});
2245 GetPhysDevSparseImageFormatProps2(physical_device, &info2, &sparse_count_2, props2.data());
2246 ASSERT_EQ(sparse_count_1, sparse_count_2);
2247 ASSERT_TRUE(CompareSparseImageFormatData(props, props2));
2248 ASSERT_TRUE(log.find("Emulating call in ICD"));
2249 }
2250 env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
2251 .set_name("modify_api_version_layer")
2252 .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
2253 .set_disable_environment("DisableEnvVar")),
2254 "modify_api_version_layer.json");
2255 env.get_test_layer().set_alter_api_version(VK_API_VERSION_1_1);
2256 { // Now do the same as above but with a layer that updates the version to 1.1 on behalf of the application
2257 InstWrapper instance(env.vulkan_functions);
2258 instance.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
2259 instance.CheckCreate();
2260 DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
2261 CreateDebugUtilsMessenger(log);
2262
2263 PFN_vkGetPhysicalDeviceSparseImageFormatProperties2 GetPhysDevSparseImageFormatProps2 =
2264 instance.load("vkGetPhysicalDeviceSparseImageFormatProperties2");
2265 ASSERT_NE(GetPhysDevSparseImageFormatProps2, nullptr);
2266
2267 uint32_t driver_count = 1;
2268 VkPhysicalDevice physical_device;
2269 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
2270 ASSERT_EQ(driver_count, 1U);
2271
2272 std::vector<VkSparseImageFormatProperties> props{};
2273 uint32_t sparse_count_1 = 0;
2274 instance->vkGetPhysicalDeviceSparseImageFormatProperties(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, VK_IMAGE_TYPE_2D,
2275 VK_SAMPLE_COUNT_4_BIT, VK_IMAGE_USAGE_STORAGE_BIT,
2276 VK_IMAGE_TILING_OPTIMAL, &sparse_count_1, nullptr);
2277 ASSERT_NE(sparse_count_1, 0U);
2278 props.resize(sparse_count_1);
2279 instance->vkGetPhysicalDeviceSparseImageFormatProperties(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, VK_IMAGE_TYPE_2D,
2280 VK_SAMPLE_COUNT_4_BIT, VK_IMAGE_USAGE_STORAGE_BIT,
2281 VK_IMAGE_TILING_OPTIMAL, &sparse_count_1, props.data());
2282 ASSERT_NE(sparse_count_1, 0U);
2283
2284 VkPhysicalDeviceSparseImageFormatInfo2 info2{
2285 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2, // sType
2286 nullptr, // pNext
2287 VK_FORMAT_R4G4_UNORM_PACK8, // format
2288 VK_IMAGE_TYPE_2D, // type
2289 VK_SAMPLE_COUNT_4_BIT, // samples
2290 VK_IMAGE_USAGE_STORAGE_BIT, // usage
2291 VK_IMAGE_TILING_OPTIMAL, // tiling
2292 };
2293 std::vector<VkSparseImageFormatProperties2> props2{};
2294 uint32_t sparse_count_2 = 0;
2295 GetPhysDevSparseImageFormatProps2(physical_device, &info2, &sparse_count_2, nullptr);
2296 ASSERT_EQ(sparse_count_1, sparse_count_2);
2297 props2.resize(sparse_count_2, VkSparseImageFormatProperties2{VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2});
2298 GetPhysDevSparseImageFormatProps2(physical_device, &info2, &sparse_count_2, props2.data());
2299 ASSERT_EQ(sparse_count_1, sparse_count_2);
2300 ASSERT_TRUE(CompareSparseImageFormatData(props, props2));
2301 ASSERT_FALSE(log.find("Emulating call in ICD"));
2302 }
2303 }
2304
2305 // Test vkGetPhysicalDeviceSparseImageFormatProperties2 and vkGetPhysicalDeviceSparseImageFormatProperties2KHR where ICD is 1.0 and
2306 // supports extension but the instance supports 1.1 and the extension
TEST(LoaderInstPhysDevExts, PhysDevSparseImageFormatProps2KHRInstanceSupports11)2307 TEST(LoaderInstPhysDevExts, PhysDevSparseImageFormatProps2KHRInstanceSupports11) {
2308 FrameworkEnvironment env{};
2309 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
2310 env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
2311 env.get_test_icd(0).physical_devices.push_back({});
2312 env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
2313 FillInRandomSparseImageFormatData(env.get_test_icd(0).physical_devices.back().sparse_image_format_properties);
2314
2315 InstWrapper instance(env.vulkan_functions);
2316 instance.create_info.set_api_version(VK_API_VERSION_1_1);
2317 instance.create_info.add_extensions(
2318 {VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_EXTENSION_NAME});
2319 instance.CheckCreate();
2320 DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
2321 CreateDebugUtilsMessenger(log);
2322
2323 PFN_vkGetPhysicalDeviceSparseImageFormatProperties2 GetPhysDevSparseImageFormatProps2 =
2324 instance.load("vkGetPhysicalDeviceSparseImageFormatProperties2");
2325 ASSERT_NE(GetPhysDevSparseImageFormatProps2, nullptr);
2326
2327 PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR GetPhysDevSparseImageFormatProps2KHR =
2328 instance.load("vkGetPhysicalDeviceSparseImageFormatProperties2KHR");
2329 ASSERT_NE(GetPhysDevSparseImageFormatProps2KHR, nullptr);
2330
2331 uint32_t driver_count = 1;
2332 VkPhysicalDevice physical_device;
2333 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
2334 ASSERT_EQ(driver_count, 1U);
2335
2336 std::vector<VkSparseImageFormatProperties> props{};
2337 uint32_t sparse_count_1 = 0;
2338 instance->vkGetPhysicalDeviceSparseImageFormatProperties(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, VK_IMAGE_TYPE_2D,
2339 VK_SAMPLE_COUNT_4_BIT, VK_IMAGE_USAGE_STORAGE_BIT,
2340 VK_IMAGE_TILING_OPTIMAL, &sparse_count_1, nullptr);
2341 ASSERT_NE(sparse_count_1, 0U);
2342 props.resize(sparse_count_1);
2343 instance->vkGetPhysicalDeviceSparseImageFormatProperties(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, VK_IMAGE_TYPE_2D,
2344 VK_SAMPLE_COUNT_4_BIT, VK_IMAGE_USAGE_STORAGE_BIT,
2345 VK_IMAGE_TILING_OPTIMAL, &sparse_count_1, props.data());
2346 ASSERT_NE(sparse_count_1, 0U);
2347
2348 VkPhysicalDeviceSparseImageFormatInfo2 info2{
2349 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2, // sType
2350 nullptr, // pNext
2351 VK_FORMAT_R4G4_UNORM_PACK8, // format
2352 VK_IMAGE_TYPE_2D, // type
2353 VK_SAMPLE_COUNT_4_BIT, // samples
2354 VK_IMAGE_USAGE_STORAGE_BIT, // usage
2355 VK_IMAGE_TILING_OPTIMAL, // tiling
2356 };
2357 std::vector<VkSparseImageFormatProperties2> props2{};
2358 uint32_t sparse_count_2 = 0;
2359 GetPhysDevSparseImageFormatProps2(physical_device, &info2, &sparse_count_2, nullptr);
2360 ASSERT_EQ(sparse_count_1, sparse_count_2);
2361 props2.resize(sparse_count_2, VkSparseImageFormatProperties2{VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2});
2362 GetPhysDevSparseImageFormatProps2(physical_device, &info2, &sparse_count_2, props2.data());
2363 ASSERT_EQ(sparse_count_1, sparse_count_2);
2364 ASSERT_TRUE(CompareSparseImageFormatData(props, props2));
2365
2366 std::vector<VkSparseImageFormatProperties2KHR> props2KHR{};
2367 uint32_t sparse_count_2_khr = 0;
2368 GetPhysDevSparseImageFormatProps2KHR(physical_device, &info2, &sparse_count_2_khr, nullptr);
2369 ASSERT_EQ(sparse_count_1, sparse_count_2_khr);
2370 props2KHR.resize(sparse_count_2, VkSparseImageFormatProperties2KHR{VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2_KHR});
2371 GetPhysDevSparseImageFormatProps2KHR(physical_device, &info2, &sparse_count_2_khr, props2KHR.data());
2372 ASSERT_EQ(sparse_count_1, sparse_count_2_khr);
2373 ASSERT_TRUE(CompareSparseImageFormatData(props, props2KHR));
2374
2375 ASSERT_FALSE(log.find("Emulating call in ICD"));
2376 }
2377
2378 // Test vkGetPhysicalDeviceSparseImageFormatProperties2 where instance supports it with some ICDs that both support
2379 // and don't support it:
2380 // ICD 0 supports
2381 // Physical device 0 does not
2382 // Physical device 1 does
2383 // Physical device 2 does not
2384 // ICD 1 doesn't support
2385 // Physical device 3 does not
2386 // ICD 2 supports
2387 // Physical device 4 does not
2388 // Physical device 5 does not
2389 // ICD 3 supports
2390 // Physical device 6 does
TEST(LoaderInstPhysDevExts, PhysDevSparseImageFormatPropsMixed)2391 TEST(LoaderInstPhysDevExts, PhysDevSparseImageFormatPropsMixed) {
2392 FrameworkEnvironment env{};
2393 const uint32_t max_icd_count = 4;
2394 const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
2395 const uint32_t max_phys_devs = 7;
2396
2397 for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
2398 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, icd != 1 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0));
2399 auto& cur_icd = env.get_test_icd(icd);
2400
2401 // ICD 1 should not have 1.1
2402 if (icd != 1) {
2403 cur_icd.icd_api_version = VK_API_VERSION_1_1;
2404 cur_icd.add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
2405 }
2406
2407 uint32_t rand_vendor_id;
2408 uint32_t rand_driver_vers;
2409 FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
2410
2411 for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
2412 uint32_t device_version = VK_API_VERSION_1_0;
2413 cur_icd.physical_devices.push_back({});
2414 auto& cur_dev = cur_icd.physical_devices.back();
2415
2416 // 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
2417 if ((icd == 0 && dev == 1) || icd == 3) {
2418 cur_dev.extensions.push_back({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0});
2419 device_version = VK_API_VERSION_1_1;
2420 }
2421
2422 // Still set physical device properties (so we can determine if device is correct API version)
2423 FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
2424 FillInRandomSparseImageFormatData(cur_dev.sparse_image_format_properties);
2425 }
2426 }
2427
2428 InstWrapper instance(env.vulkan_functions);
2429 instance.create_info.set_api_version(VK_API_VERSION_1_1);
2430 instance.CheckCreate();
2431
2432 PFN_vkGetPhysicalDeviceSparseImageFormatProperties2 GetPhysDevSparseImageFormatProps2 =
2433 instance.load("vkGetPhysicalDeviceSparseImageFormatProperties2");
2434 ASSERT_NE(GetPhysDevSparseImageFormatProps2, nullptr);
2435
2436 uint32_t device_count = max_phys_devs;
2437 std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
2438 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
2439 ASSERT_EQ(device_count, max_phys_devs);
2440
2441 for (uint32_t dev = 0; dev < device_count; ++dev) {
2442 std::vector<VkSparseImageFormatProperties> props{};
2443 uint32_t sparse_count_1 = 0;
2444 instance->vkGetPhysicalDeviceSparseImageFormatProperties(
2445 physical_devices[dev], VK_FORMAT_R4G4_UNORM_PACK8, VK_IMAGE_TYPE_2D, VK_SAMPLE_COUNT_4_BIT, VK_IMAGE_USAGE_STORAGE_BIT,
2446 VK_IMAGE_TILING_OPTIMAL, &sparse_count_1, nullptr);
2447 ASSERT_NE(sparse_count_1, 0U);
2448 props.resize(sparse_count_1);
2449 instance->vkGetPhysicalDeviceSparseImageFormatProperties(
2450 physical_devices[dev], VK_FORMAT_R4G4_UNORM_PACK8, VK_IMAGE_TYPE_2D, VK_SAMPLE_COUNT_4_BIT, VK_IMAGE_USAGE_STORAGE_BIT,
2451 VK_IMAGE_TILING_OPTIMAL, &sparse_count_1, props.data());
2452 ASSERT_NE(sparse_count_1, 0U);
2453
2454 VkPhysicalDeviceSparseImageFormatInfo2 info2{
2455 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2, // sType
2456 nullptr, // pNext
2457 VK_FORMAT_R4G4_UNORM_PACK8, // format
2458 VK_IMAGE_TYPE_2D, // type
2459 VK_SAMPLE_COUNT_4_BIT, // samples
2460 VK_IMAGE_USAGE_STORAGE_BIT, // usage
2461 VK_IMAGE_TILING_OPTIMAL, // tiling
2462 };
2463 std::vector<VkSparseImageFormatProperties2> props2{};
2464 uint32_t sparse_count_2 = 0;
2465 GetPhysDevSparseImageFormatProps2(physical_devices[dev], &info2, &sparse_count_2, nullptr);
2466 ASSERT_EQ(sparse_count_1, sparse_count_2);
2467 props2.resize(sparse_count_2, VkSparseImageFormatProperties2{VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2});
2468 GetPhysDevSparseImageFormatProps2(physical_devices[dev], &info2, &sparse_count_2, props2.data());
2469 ASSERT_EQ(sparse_count_1, sparse_count_2);
2470 ASSERT_TRUE(CompareSparseImageFormatData(props, props2));
2471 }
2472 }
2473
2474 //
2475 // VK_KHR_external_memory_capabilities
2476 //
2477
2478 // Test vkGetPhysicalDeviceExternalBufferPropertiesKHR where nothing supports it.
TEST(LoaderInstPhysDevExts, PhysDevExtBufPropsKHRNoSupport)2479 TEST(LoaderInstPhysDevExts, PhysDevExtBufPropsKHRNoSupport) {
2480 FrameworkEnvironment env{};
2481 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
2482 env.get_test_icd(0).physical_devices.push_back({});
2483
2484 InstWrapper instance(env.vulkan_functions);
2485 instance.CheckCreate();
2486
2487 PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR GetPhysicalDeviceExternalBufferPropertiesKHR =
2488 instance.load("vkGetPhysicalDeviceExternalBufferPropertiesKHR");
2489 ASSERT_EQ(GetPhysicalDeviceExternalBufferPropertiesKHR, nullptr);
2490 }
2491
2492 // Test vkGetPhysicalDeviceExternalBufferPropertiesKHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevExtBufPropsKHRNoICDSupport)2493 TEST(LoaderInstPhysDevExts, PhysDevExtBufPropsKHRNoICDSupport) {
2494 FrameworkEnvironment env{};
2495 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
2496 env.get_test_icd(0).physical_devices.push_back({});
2497
2498 InstWrapper instance(env.vulkan_functions);
2499 instance.create_info.add_extension(VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME);
2500 instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
2501
2502 PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR GetPhysicalDeviceExternalBufferPropertiesKHR =
2503 instance.load("vkGetPhysicalDeviceExternalBufferPropertiesKHR");
2504 ASSERT_EQ(GetPhysicalDeviceExternalBufferPropertiesKHR, nullptr);
2505 }
2506
2507 // Fill in random but valid data into the external memorydata struct for the current physical device
FillInRandomExtMemoryData(VkExternalMemoryProperties& props)2508 void FillInRandomExtMemoryData(VkExternalMemoryProperties& props) {
2509 props.externalMemoryFeatures = static_cast<VkExternalMemoryFeatureFlags>((rand() % 6) + 1);
2510 props.exportFromImportedHandleTypes = static_cast<VkExternalMemoryHandleTypeFlags>((rand() % 0x1FFE) + 1);
2511 props.compatibleHandleTypes = static_cast<VkExternalMemoryHandleTypeFlags>((rand() % 0x1FFE) + 1);
2512 }
2513
2514 // Compare the external memory data structs
CompareExtMemoryData(const VkExternalMemoryProperties& props1, const VkExternalMemoryProperties& props2, bool supported = true)2515 bool CompareExtMemoryData(const VkExternalMemoryProperties& props1, const VkExternalMemoryProperties& props2,
2516 bool supported = true) {
2517 bool equal = true;
2518 if (supported) {
2519 equal = equal && props1.externalMemoryFeatures == props2.externalMemoryFeatures;
2520 equal = equal && props1.exportFromImportedHandleTypes == props2.exportFromImportedHandleTypes;
2521 equal = equal && props1.compatibleHandleTypes == props2.compatibleHandleTypes;
2522 } else {
2523 equal = equal && 0 == props2.externalMemoryFeatures;
2524 equal = equal && 0 == props2.exportFromImportedHandleTypes;
2525 equal = equal && 0 == props2.compatibleHandleTypes;
2526 }
2527 return equal;
2528 }
2529
2530 // Test vkGetPhysicalDeviceExternalBufferPropertiesKHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, PhysDevExtBufProps2KHRInstanceAndICDSupport)2531 TEST(LoaderInstPhysDevExts, PhysDevExtBufProps2KHRInstanceAndICDSupport) {
2532 FrameworkEnvironment env{};
2533 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
2534 env.get_test_icd(0).add_instance_extension({VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME});
2535 env.get_test_icd(0).physical_devices.push_back({});
2536 FillInRandomExtMemoryData(env.get_test_icd(0).physical_devices.back().external_memory_properties);
2537
2538 InstWrapper instance(env.vulkan_functions);
2539 instance.create_info.add_extension(VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME);
2540 instance.CheckCreate();
2541
2542 PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR GetPhysicalDeviceExternalBufferPropertiesKHR =
2543 instance.load("vkGetPhysicalDeviceExternalBufferPropertiesKHR");
2544 ASSERT_NE(GetPhysicalDeviceExternalBufferPropertiesKHR, nullptr);
2545
2546 uint32_t driver_count = 1;
2547 VkPhysicalDevice physical_device;
2548 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
2549 ASSERT_EQ(driver_count, 1U);
2550
2551 VkPhysicalDeviceExternalBufferInfoKHR info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHR};
2552 VkExternalBufferPropertiesKHR props{VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHR};
2553 GetPhysicalDeviceExternalBufferPropertiesKHR(physical_device, &info, &props);
2554 ASSERT_TRUE(CompareExtMemoryData(env.get_test_icd(0).physical_devices.back().external_memory_properties,
2555 props.externalMemoryProperties));
2556 }
2557
2558 // Test vkGetPhysicalDeviceExternalBufferProperties where instance supports, an ICD, and a device under that ICD
2559 // also support, so everything should work and return properly.
2560 // Also check if the application didn't enable 1.1 and when a layer 'upgrades' the api version to 1.1
TEST(LoaderInstPhysDevExts, PhysDevExtBufProps2Simple)2561 TEST(LoaderInstPhysDevExts, PhysDevExtBufProps2Simple) {
2562 FrameworkEnvironment env{};
2563 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
2564 env.get_test_icd(0).icd_api_version = VK_API_VERSION_1_1;
2565 env.get_test_icd(0).add_instance_extension({VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME});
2566 env.get_test_icd(0).physical_devices.push_back({});
2567 env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME, 0});
2568 FillInRandomExtMemoryData(env.get_test_icd(0).physical_devices.back().external_memory_properties);
2569 {
2570 InstWrapper instance(env.vulkan_functions);
2571 instance.create_info.set_api_version(VK_API_VERSION_1_1);
2572 instance.CheckCreate();
2573
2574 PFN_vkGetPhysicalDeviceExternalBufferProperties GetPhysicalDeviceExternalBufferProperties =
2575 instance.load("vkGetPhysicalDeviceExternalBufferProperties");
2576 ASSERT_NE(GetPhysicalDeviceExternalBufferProperties, nullptr);
2577
2578 uint32_t driver_count = 1;
2579 VkPhysicalDevice physical_device;
2580 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
2581 ASSERT_EQ(driver_count, 1U);
2582
2583 VkPhysicalDeviceExternalBufferInfo info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO};
2584 VkExternalBufferProperties props{VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES};
2585 GetPhysicalDeviceExternalBufferProperties(physical_device, &info, &props);
2586 ASSERT_TRUE(CompareExtMemoryData(env.get_test_icd(0).physical_devices.back().external_memory_properties,
2587 props.externalMemoryProperties));
2588 }
2589 { // Now do the same logic but the application didn't enable 1.0 or the extension so they get the emulated call
2590 InstWrapper instance(env.vulkan_functions);
2591 instance.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
2592 instance.CheckCreate();
2593 DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
2594 CreateDebugUtilsMessenger(log);
2595
2596 PFN_vkGetPhysicalDeviceExternalBufferProperties GetPhysicalDeviceExternalBufferProperties =
2597 instance.load("vkGetPhysicalDeviceExternalBufferProperties");
2598 ASSERT_NE(GetPhysicalDeviceExternalBufferProperties, nullptr);
2599
2600 uint32_t driver_count = 1;
2601 VkPhysicalDevice physical_device;
2602 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
2603 ASSERT_EQ(driver_count, 1U);
2604
2605 VkPhysicalDeviceExternalBufferInfo info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO};
2606 VkExternalBufferProperties props{VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES};
2607 GetPhysicalDeviceExternalBufferProperties(physical_device, &info, &props);
2608 // Compare against 'zeroed' out VkExternalMemoryProperties
2609 ASSERT_TRUE(CompareExtMemoryData(VkExternalMemoryProperties{}, props.externalMemoryProperties));
2610 ASSERT_TRUE(log.find("Emulating call in ICD"));
2611 }
2612 env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
2613 .set_name("modify_api_version_layer")
2614 .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
2615 .set_disable_environment("DisableEnvVar")),
2616 "modify_api_version_layer.json");
2617 env.get_test_layer().set_alter_api_version(VK_API_VERSION_1_1);
2618 { // Now do the same as above but with a layer that updates the version to 1.1 on behalf of the application
2619 InstWrapper instance(env.vulkan_functions);
2620 instance.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
2621 instance.CheckCreate();
2622 DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
2623 CreateDebugUtilsMessenger(log);
2624
2625 PFN_vkGetPhysicalDeviceExternalBufferProperties GetPhysicalDeviceExternalBufferProperties =
2626 instance.load("vkGetPhysicalDeviceExternalBufferProperties");
2627 ASSERT_NE(GetPhysicalDeviceExternalBufferProperties, nullptr);
2628
2629 uint32_t driver_count = 1;
2630 VkPhysicalDevice physical_device;
2631 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
2632 ASSERT_EQ(driver_count, 1U);
2633
2634 VkPhysicalDeviceExternalBufferInfo info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO};
2635 VkExternalBufferProperties props{VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES};
2636 GetPhysicalDeviceExternalBufferProperties(physical_device, &info, &props);
2637 ASSERT_TRUE(CompareExtMemoryData(env.get_test_icd(0).physical_devices.back().external_memory_properties,
2638 props.externalMemoryProperties));
2639 ASSERT_FALSE(log.find("Emulating call in ICD"));
2640 }
2641 }
2642
2643 // Test vkGetPhysicalDeviceExternalBufferProperties where instance supports it with some ICDs that both support
2644 // and don't support it:
2645 // ICD 0 supports
2646 // Physical device 0 does not
2647 // Physical device 1 does
2648 // Physical device 2 does not
2649 // ICD 1 doesn't support
2650 // Physical device 3 does not
2651 // ICD 2 supports
2652 // Physical device 4 does not
2653 // Physical device 5 does not
2654 // ICD 3 supports
2655 // Physical device 6 does
TEST(LoaderInstPhysDevExts, PhysDevExtBufPropsMixed)2656 TEST(LoaderInstPhysDevExts, PhysDevExtBufPropsMixed) {
2657 FrameworkEnvironment env{};
2658 const uint32_t max_icd_count = 4;
2659 const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
2660 const uint32_t max_phys_devs = 7;
2661
2662 for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
2663 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, icd != 1 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0));
2664 auto& cur_icd = env.get_test_icd(icd);
2665
2666 // ICD 1 should not have 1.1
2667 if (icd != 1) {
2668 cur_icd.icd_api_version = VK_API_VERSION_1_1;
2669 cur_icd.add_instance_extension({VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME});
2670 }
2671
2672 uint32_t rand_vendor_id;
2673 uint32_t rand_driver_vers;
2674 FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
2675
2676 for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
2677 uint32_t device_version = VK_API_VERSION_1_0;
2678 cur_icd.physical_devices.push_back({});
2679 auto& cur_dev = cur_icd.physical_devices.back();
2680
2681 // 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
2682 if ((icd == 0 && dev == 1) || icd == 3) {
2683 cur_dev.extensions.push_back({VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME, 0});
2684 device_version = VK_API_VERSION_1_1;
2685 }
2686
2687 // Still set physical device properties (so we can determine if device is correct API version)
2688 FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
2689 FillInRandomExtMemoryData(cur_dev.external_memory_properties);
2690 }
2691 }
2692
2693 InstWrapper instance(env.vulkan_functions);
2694 instance.create_info.set_api_version(VK_API_VERSION_1_1);
2695 instance.CheckCreate();
2696
2697 PFN_vkGetPhysicalDeviceExternalBufferProperties GetPhysicalDeviceExternalBufferProperties =
2698 instance.load("vkGetPhysicalDeviceExternalBufferProperties");
2699 ASSERT_NE(GetPhysicalDeviceExternalBufferProperties, nullptr);
2700
2701 uint32_t device_count = max_phys_devs;
2702 std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
2703 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
2704 ASSERT_EQ(device_count, max_phys_devs);
2705
2706 for (uint32_t dev = 0; dev < device_count; ++dev) {
2707 VkPhysicalDeviceProperties pd_props{};
2708 instance->vkGetPhysicalDeviceProperties(physical_devices[dev], &pd_props);
2709
2710 for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
2711 auto& cur_icd = env.get_test_icd(icd);
2712 bool found = false;
2713 for (uint32_t pd = 0; pd < dev_counts[icd]; ++pd) {
2714 auto& cur_dev = cur_icd.physical_devices[pd];
2715 // Find the ICD device matching the physical device we're looking at info for so we can compare the
2716 // physical devices info with the returned info.
2717 if (cur_dev.properties.apiVersion == pd_props.apiVersion && cur_dev.properties.deviceID == pd_props.deviceID &&
2718 cur_dev.properties.deviceType == pd_props.deviceType &&
2719 cur_dev.properties.driverVersion == pd_props.driverVersion &&
2720 cur_dev.properties.vendorID == pd_props.vendorID) {
2721 VkPhysicalDeviceExternalBufferInfo info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO};
2722 VkExternalBufferProperties props{VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES};
2723 GetPhysicalDeviceExternalBufferProperties(physical_devices[dev], &info, &props);
2724 // No driver support for extension or 1.1 for ICD 1, all others support
2725 ASSERT_TRUE(CompareExtMemoryData(cur_dev.external_memory_properties, props.externalMemoryProperties, icd != 1));
2726 found = true;
2727 break;
2728 }
2729 }
2730 if (found) {
2731 break;
2732 }
2733 }
2734 }
2735 }
2736
2737 //
2738 // VK_KHR_external_semaphore_capabilities
2739 //
2740
2741 // Test vkGetPhysicalDeviceExternalSemaphorePropertiesKHR where nothing supports it.
TEST(LoaderInstPhysDevExts, PhysDevExtSemPropsKHRNoSupport)2742 TEST(LoaderInstPhysDevExts, PhysDevExtSemPropsKHRNoSupport) {
2743 FrameworkEnvironment env{};
2744 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
2745 env.get_test_icd(0).physical_devices.push_back({});
2746
2747 InstWrapper instance(env.vulkan_functions);
2748 instance.CheckCreate();
2749
2750 PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR GetPhysicalDeviceExternalSemaphorePropertiesKHR =
2751 instance.load("vkGetPhysicalDeviceExternalSemaphorePropertiesKHR");
2752 ASSERT_EQ(GetPhysicalDeviceExternalSemaphorePropertiesKHR, nullptr);
2753 }
2754
2755 // Test vkGetPhysicalDeviceExternalSemaphorePropertiesKHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevExtSemPropsKHRNoICDSupport)2756 TEST(LoaderInstPhysDevExts, PhysDevExtSemPropsKHRNoICDSupport) {
2757 FrameworkEnvironment env{};
2758 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
2759 env.get_test_icd(0).physical_devices.push_back({});
2760
2761 InstWrapper instance(env.vulkan_functions);
2762 instance.create_info.add_extension(VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME);
2763 instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
2764
2765 PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR GetPhysicalDeviceExternalSemaphorePropertiesKHR =
2766 instance.load("vkGetPhysicalDeviceExternalSemaphorePropertiesKHR");
2767 ASSERT_EQ(GetPhysicalDeviceExternalSemaphorePropertiesKHR, nullptr);
2768 }
2769
2770 // Fill in random but valid data into the external semaphore data struct for the current physical device
FillInRandomExtSemData(VkExternalSemaphoreProperties& props)2771 void FillInRandomExtSemData(VkExternalSemaphoreProperties& props) {
2772 props.sType = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES;
2773 props.pNext = nullptr;
2774 props.exportFromImportedHandleTypes = static_cast<VkExternalSemaphoreHandleTypeFlags>((rand() % 0xFFF) + 1);
2775 props.compatibleHandleTypes = static_cast<VkExternalSemaphoreHandleTypeFlags>((rand() % 0xFFF) + 1);
2776 props.externalSemaphoreFeatures = static_cast<VkExternalSemaphoreFeatureFlags>((rand() % 0xFFF) + 1);
2777 }
2778
2779 // Compare the external semaphore data structs
CompareExtSemaphoreData(const VkExternalSemaphoreProperties& props1, const VkExternalSemaphoreProperties& props2, bool supported = true)2780 bool CompareExtSemaphoreData(const VkExternalSemaphoreProperties& props1, const VkExternalSemaphoreProperties& props2,
2781 bool supported = true) {
2782 bool equal = true;
2783 if (supported) {
2784 equal = equal && props1.externalSemaphoreFeatures == props2.externalSemaphoreFeatures;
2785 equal = equal && props1.exportFromImportedHandleTypes == props2.exportFromImportedHandleTypes;
2786 equal = equal && props1.compatibleHandleTypes == props2.compatibleHandleTypes;
2787 } else {
2788 equal = equal && 0 == props2.externalSemaphoreFeatures;
2789 equal = equal && 0 == props2.exportFromImportedHandleTypes;
2790 equal = equal && 0 == props2.compatibleHandleTypes;
2791 }
2792 return equal;
2793 }
2794
2795 // Test vkGetPhysicalDeviceExternalSemaphorePropertiesKHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, PhysDevExtSemProps2KHRInstanceAndICDSupport)2796 TEST(LoaderInstPhysDevExts, PhysDevExtSemProps2KHRInstanceAndICDSupport) {
2797 FrameworkEnvironment env{};
2798 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
2799 env.get_test_icd(0).add_instance_extension({VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME});
2800 env.get_test_icd(0).physical_devices.push_back({});
2801 FillInRandomExtSemData(env.get_test_icd(0).physical_devices.back().external_semaphore_properties);
2802
2803 InstWrapper instance(env.vulkan_functions);
2804 instance.create_info.add_extension(VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME);
2805 instance.CheckCreate();
2806
2807 PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR GetPhysicalDeviceExternalSemaphorePropertiesKHR =
2808 instance.load("vkGetPhysicalDeviceExternalSemaphorePropertiesKHR");
2809 ASSERT_NE(GetPhysicalDeviceExternalSemaphorePropertiesKHR, nullptr);
2810
2811 uint32_t driver_count = 1;
2812 VkPhysicalDevice physical_device;
2813 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
2814 ASSERT_EQ(driver_count, 1U);
2815
2816 VkPhysicalDeviceExternalSemaphoreInfoKHR info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR};
2817 VkExternalSemaphorePropertiesKHR props{VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR};
2818 GetPhysicalDeviceExternalSemaphorePropertiesKHR(physical_device, &info, &props);
2819 ASSERT_TRUE(CompareExtSemaphoreData(env.get_test_icd(0).physical_devices.back().external_semaphore_properties, props));
2820 }
2821
2822 // Test vkGetPhysicalDeviceExternalSemaphoreProperties where instance supports, an ICD, and a device under that ICD
2823 // also support, so everything should work and return properly.
2824 // Also check if the application didn't enable 1.1 and when a layer 'upgrades' the api version to 1.1
TEST(LoaderInstPhysDevExts, PhysDevExtSemProps2Simple)2825 TEST(LoaderInstPhysDevExts, PhysDevExtSemProps2Simple) {
2826 FrameworkEnvironment env{};
2827 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
2828 env.get_test_icd(0).icd_api_version = VK_API_VERSION_1_1;
2829 env.get_test_icd(0).add_instance_extension({VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME});
2830 env.get_test_icd(0).physical_devices.push_back({});
2831 env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME, 0});
2832 FillInRandomExtSemData(env.get_test_icd(0).physical_devices.back().external_semaphore_properties);
2833 {
2834 InstWrapper instance(env.vulkan_functions);
2835 instance.create_info.set_api_version(VK_API_VERSION_1_1);
2836 instance.CheckCreate();
2837
2838 PFN_vkGetPhysicalDeviceExternalSemaphoreProperties GetPhysicalDeviceExternalSemaphoreProperties =
2839 instance.load("vkGetPhysicalDeviceExternalSemaphoreProperties");
2840 ASSERT_NE(GetPhysicalDeviceExternalSemaphoreProperties, nullptr);
2841
2842 uint32_t driver_count = 1;
2843 VkPhysicalDevice physical_device;
2844 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
2845 ASSERT_EQ(driver_count, 1U);
2846
2847 VkPhysicalDeviceExternalSemaphoreInfo info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO};
2848 VkExternalSemaphoreProperties props{VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES};
2849 GetPhysicalDeviceExternalSemaphoreProperties(physical_device, &info, &props);
2850 ASSERT_TRUE(CompareExtSemaphoreData(env.get_test_icd(0).physical_devices.back().external_semaphore_properties, props));
2851 }
2852 { // Now do the same logic but the application didn't enable 1.0 or the extension so they get the emulated call
2853 InstWrapper instance(env.vulkan_functions);
2854 instance.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
2855 instance.CheckCreate();
2856 DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
2857 CreateDebugUtilsMessenger(log);
2858 PFN_vkGetPhysicalDeviceExternalSemaphoreProperties GetPhysicalDeviceExternalSemaphoreProperties =
2859 instance.load("vkGetPhysicalDeviceExternalSemaphoreProperties");
2860 ASSERT_NE(GetPhysicalDeviceExternalSemaphoreProperties, nullptr);
2861
2862 uint32_t driver_count = 1;
2863 VkPhysicalDevice physical_device;
2864 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
2865 ASSERT_EQ(driver_count, 1U);
2866
2867 VkPhysicalDeviceExternalSemaphoreInfo info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO};
2868 VkExternalSemaphoreProperties props{VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES};
2869 GetPhysicalDeviceExternalSemaphoreProperties(physical_device, &info, &props);
2870 // Compare against 'zeroed' out VkExternalSemaphoreProperties
2871 ASSERT_TRUE(CompareExtSemaphoreData(VkExternalSemaphoreProperties{}, props));
2872 ASSERT_TRUE(log.find("Emulating call in ICD"));
2873 }
2874 env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
2875 .set_name("modify_api_version_layer")
2876 .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
2877 .set_disable_environment("DisableEnvVar")),
2878 "modify_api_version_layer.json");
2879 env.get_test_layer().set_alter_api_version(VK_API_VERSION_1_1);
2880 { // Now do the same as above but with a layer that updates the version to 1.1 on behalf of the application
2881 InstWrapper instance(env.vulkan_functions);
2882 instance.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
2883 instance.CheckCreate();
2884 DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
2885 CreateDebugUtilsMessenger(log);
2886 PFN_vkGetPhysicalDeviceExternalSemaphoreProperties GetPhysicalDeviceExternalSemaphoreProperties =
2887 instance.load("vkGetPhysicalDeviceExternalSemaphoreProperties");
2888 ASSERT_NE(GetPhysicalDeviceExternalSemaphoreProperties, nullptr);
2889
2890 uint32_t driver_count = 1;
2891 VkPhysicalDevice physical_device;
2892 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
2893 ASSERT_EQ(driver_count, 1U);
2894
2895 VkPhysicalDeviceExternalSemaphoreInfo info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO};
2896 VkExternalSemaphoreProperties props{VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES};
2897 GetPhysicalDeviceExternalSemaphoreProperties(physical_device, &info, &props);
2898 ASSERT_TRUE(CompareExtSemaphoreData(env.get_test_icd(0).physical_devices.back().external_semaphore_properties, props));
2899 ASSERT_FALSE(log.find("Emulating call in ICD"));
2900 }
2901 }
2902
2903 // Test vkGetPhysicalDeviceExternalSemaphoreProperties where instance supports it with some ICDs that both support
2904 // and don't support it:
2905 // ICD 0 supports
2906 // Physical device 0 does not
2907 // Physical device 1 does
2908 // Physical device 2 does not
2909 // ICD 1 doesn't support
2910 // Physical device 3 does not
2911 // ICD 2 supports
2912 // Physical device 4 does not
2913 // Physical device 5 does not
2914 // ICD 3 supports
2915 // Physical device 6 does
TEST(LoaderInstPhysDevExts, PhysDevExtSemPropsMixed)2916 TEST(LoaderInstPhysDevExts, PhysDevExtSemPropsMixed) {
2917 FrameworkEnvironment env{};
2918 const uint32_t max_icd_count = 4;
2919 const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
2920 const uint32_t max_phys_devs = 7;
2921
2922 for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
2923 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, icd != 1 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0));
2924 auto& cur_icd = env.get_test_icd(icd);
2925
2926 // ICD 1 should not have 1.1
2927 if (icd != 1) {
2928 cur_icd.icd_api_version = VK_API_VERSION_1_1;
2929 cur_icd.add_instance_extension({VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME});
2930 }
2931
2932 uint32_t rand_vendor_id;
2933 uint32_t rand_driver_vers;
2934 FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
2935
2936 for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
2937 uint32_t device_version = VK_API_VERSION_1_0;
2938 cur_icd.physical_devices.push_back({});
2939 auto& cur_dev = cur_icd.physical_devices.back();
2940
2941 // 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
2942 if ((icd == 0 && dev == 1) || icd == 3) {
2943 cur_dev.extensions.push_back({VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME, 0});
2944 device_version = VK_API_VERSION_1_1;
2945 }
2946
2947 // Still set physical device properties (so we can determine if device is correct API version)
2948 FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
2949 FillInRandomExtSemData(cur_dev.external_semaphore_properties);
2950 }
2951 }
2952
2953 InstWrapper instance(env.vulkan_functions);
2954 instance.create_info.set_api_version(VK_API_VERSION_1_1);
2955 instance.CheckCreate();
2956
2957 PFN_vkGetPhysicalDeviceExternalSemaphoreProperties GetPhysicalDeviceExternalSemaphoreProperties =
2958 instance.load("vkGetPhysicalDeviceExternalSemaphoreProperties");
2959 ASSERT_NE(GetPhysicalDeviceExternalSemaphoreProperties, nullptr);
2960
2961 uint32_t device_count = max_phys_devs;
2962 std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
2963 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
2964 ASSERT_EQ(device_count, max_phys_devs);
2965
2966 for (uint32_t dev = 0; dev < device_count; ++dev) {
2967 VkPhysicalDeviceProperties pd_props{};
2968 instance->vkGetPhysicalDeviceProperties(physical_devices[dev], &pd_props);
2969
2970 for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
2971 auto& cur_icd = env.get_test_icd(icd);
2972 bool found = false;
2973 for (uint32_t pd = 0; pd < dev_counts[icd]; ++pd) {
2974 auto& cur_dev = cur_icd.physical_devices[pd];
2975 // Find the ICD device matching the physical device we're looking at info for so we can compare the
2976 // physical devices info with the returned info.
2977 if (cur_dev.properties.apiVersion == pd_props.apiVersion && cur_dev.properties.deviceID == pd_props.deviceID &&
2978 cur_dev.properties.deviceType == pd_props.deviceType &&
2979 cur_dev.properties.driverVersion == pd_props.driverVersion &&
2980 cur_dev.properties.vendorID == pd_props.vendorID) {
2981 VkPhysicalDeviceExternalSemaphoreInfo info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO};
2982 VkExternalSemaphoreProperties props{VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES};
2983 GetPhysicalDeviceExternalSemaphoreProperties(physical_devices[dev], &info, &props);
2984 // No driver support for extension or 1.1 for ICD 1, all others support
2985 ASSERT_TRUE(CompareExtSemaphoreData(cur_dev.external_semaphore_properties, props, icd != 1));
2986 found = true;
2987 break;
2988 }
2989 }
2990 if (found) {
2991 break;
2992 }
2993 }
2994 }
2995 }
2996
2997 //
2998 // VK_KHR_external_fence_capabilities
2999 //
3000
3001 // Test vkGetPhysicalDeviceExternalFencePropertiesKHR where nothing supports it.
TEST(LoaderInstPhysDevExts, PhysDevExtFencePropsKHRNoSupport)3002 TEST(LoaderInstPhysDevExts, PhysDevExtFencePropsKHRNoSupport) {
3003 FrameworkEnvironment env{};
3004 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
3005 env.get_test_icd(0).physical_devices.push_back({});
3006
3007 InstWrapper instance(env.vulkan_functions);
3008 instance.CheckCreate();
3009
3010 PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR GetPhysicalDeviceExternalFencePropertiesKHR =
3011 instance.load("vkGetPhysicalDeviceExternalFencePropertiesKHR");
3012 ASSERT_EQ(GetPhysicalDeviceExternalFencePropertiesKHR, nullptr);
3013 }
3014
3015 // Test vkGetPhysicalDeviceExternalFencePropertiesKHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevExtFencePropsKHRNoICDSupport)3016 TEST(LoaderInstPhysDevExts, PhysDevExtFencePropsKHRNoICDSupport) {
3017 FrameworkEnvironment env{};
3018 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
3019 env.get_test_icd(0).physical_devices.push_back({});
3020
3021 InstWrapper instance(env.vulkan_functions);
3022 instance.create_info.add_extension(VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME);
3023 instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
3024
3025 PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR GetPhysicalDeviceExternalFencePropertiesKHR =
3026 instance.load("vkGetPhysicalDeviceExternalFencePropertiesKHR");
3027 ASSERT_EQ(GetPhysicalDeviceExternalFencePropertiesKHR, nullptr);
3028 }
3029
3030 // Fill in random but valid data into the external fence data struct for the current physical device
FillInRandomExtFenceData(VkExternalFenceProperties& props)3031 void FillInRandomExtFenceData(VkExternalFenceProperties& props) {
3032 props.sType = VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES;
3033 props.pNext = nullptr;
3034 props.exportFromImportedHandleTypes = static_cast<VkExternalFenceHandleTypeFlags>((rand() % 0xFFF) + 1);
3035 props.compatibleHandleTypes = static_cast<VkExternalFenceHandleTypeFlags>((rand() % 0xFFF) + 1);
3036 props.externalFenceFeatures = static_cast<VkExternalFenceFeatureFlags>((rand() % 0xFFF) + 1);
3037 }
3038
3039 // Compare the external fence data structs
CompareExtFenceData(const VkExternalFenceProperties& props1, const VkExternalFenceProperties& props2, bool supported = true)3040 bool CompareExtFenceData(const VkExternalFenceProperties& props1, const VkExternalFenceProperties& props2, bool supported = true) {
3041 bool equal = true;
3042 if (supported) {
3043 equal = equal && props1.externalFenceFeatures == props2.externalFenceFeatures;
3044 equal = equal && props1.exportFromImportedHandleTypes == props2.exportFromImportedHandleTypes;
3045 equal = equal && props1.compatibleHandleTypes == props2.compatibleHandleTypes;
3046 } else {
3047 equal = equal && 0 == props2.externalFenceFeatures;
3048 equal = equal && 0 == props2.exportFromImportedHandleTypes;
3049 equal = equal && 0 == props2.compatibleHandleTypes;
3050 }
3051 return equal;
3052 }
3053
3054 // Test vkGetPhysicalDeviceExternalFencePropertiesKHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, PhysDevExtFenceProps2KHRInstanceAndICDSupport)3055 TEST(LoaderInstPhysDevExts, PhysDevExtFenceProps2KHRInstanceAndICDSupport) {
3056 FrameworkEnvironment env{};
3057 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
3058 env.get_test_icd(0).add_instance_extension({VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME});
3059 env.get_test_icd(0).physical_devices.push_back({});
3060 FillInRandomExtFenceData(env.get_test_icd(0).physical_devices.back().external_fence_properties);
3061
3062 InstWrapper instance(env.vulkan_functions);
3063 instance.create_info.add_extension(VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME);
3064 instance.CheckCreate();
3065
3066 PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR GetPhysicalDeviceExternalFencePropertiesKHR =
3067 instance.load("vkGetPhysicalDeviceExternalFencePropertiesKHR");
3068 ASSERT_NE(GetPhysicalDeviceExternalFencePropertiesKHR, nullptr);
3069
3070 uint32_t driver_count = 1;
3071 VkPhysicalDevice physical_device;
3072 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
3073 ASSERT_EQ(driver_count, 1U);
3074
3075 VkPhysicalDeviceExternalFenceInfoKHR info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO_KHR};
3076 VkExternalFencePropertiesKHR props{VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES_KHR};
3077 GetPhysicalDeviceExternalFencePropertiesKHR(physical_device, &info, &props);
3078 ASSERT_TRUE(CompareExtFenceData(env.get_test_icd(0).physical_devices.back().external_fence_properties, props));
3079 }
3080
3081 // Test vkGetPhysicalDeviceExternalFenceProperties where instance supports, an ICD, and a device under that ICD
3082 // also support, so everything should work and return properly.
3083 // Also check if the application didn't enable 1.1 and when a layer 'upgrades' the api version to 1.1
TEST(LoaderInstPhysDevExts, PhysDevExtFenceProps2Simple)3084 TEST(LoaderInstPhysDevExts, PhysDevExtFenceProps2Simple) {
3085 FrameworkEnvironment env{};
3086 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
3087 env.get_test_icd(0).icd_api_version = VK_API_VERSION_1_1;
3088 env.get_test_icd(0).add_instance_extension({VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME});
3089 env.get_test_icd(0).physical_devices.push_back({});
3090 env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME, 0});
3091 FillInRandomExtFenceData(env.get_test_icd(0).physical_devices.back().external_fence_properties);
3092 {
3093 InstWrapper instance(env.vulkan_functions);
3094 instance.create_info.set_api_version(VK_API_VERSION_1_1);
3095 instance.CheckCreate();
3096
3097 PFN_vkGetPhysicalDeviceExternalFenceProperties GetPhysicalDeviceExternalFenceProperties =
3098 instance.load("vkGetPhysicalDeviceExternalFenceProperties");
3099 ASSERT_NE(GetPhysicalDeviceExternalFenceProperties, nullptr);
3100
3101 uint32_t driver_count = 1;
3102 VkPhysicalDevice physical_device;
3103 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
3104 ASSERT_EQ(driver_count, 1U);
3105
3106 VkPhysicalDeviceExternalFenceInfo info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO};
3107 VkExternalFenceProperties props{VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES};
3108 GetPhysicalDeviceExternalFenceProperties(physical_device, &info, &props);
3109 ASSERT_TRUE(CompareExtFenceData(env.get_test_icd(0).physical_devices.back().external_fence_properties, props));
3110 }
3111 { // Now do the same logic but the application didn't enable 1.0 or the extension so they get the emulated call
3112 InstWrapper instance(env.vulkan_functions);
3113 instance.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
3114 instance.CheckCreate();
3115 DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
3116 CreateDebugUtilsMessenger(log);
3117
3118 PFN_vkGetPhysicalDeviceExternalFenceProperties GetPhysicalDeviceExternalFenceProperties =
3119 instance.load("vkGetPhysicalDeviceExternalFenceProperties");
3120 ASSERT_NE(GetPhysicalDeviceExternalFenceProperties, nullptr);
3121
3122 uint32_t driver_count = 1;
3123 VkPhysicalDevice physical_device;
3124 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
3125 ASSERT_EQ(driver_count, 1U);
3126
3127 VkPhysicalDeviceExternalFenceInfo info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO};
3128 VkExternalFenceProperties props{VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES};
3129 GetPhysicalDeviceExternalFenceProperties(physical_device, &info, &props);
3130 // Compare against 'zeroed' out VkExternalFenceProperties
3131 ASSERT_TRUE(CompareExtFenceData(VkExternalFenceProperties{}, props));
3132 ASSERT_TRUE(log.find("Emulating call in ICD"));
3133 }
3134 env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
3135 .set_name("modify_api_version_layer")
3136 .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
3137 .set_disable_environment("DisableEnvVar")),
3138 "modify_api_version_layer.json");
3139 env.get_test_layer().set_alter_api_version(VK_API_VERSION_1_1);
3140 { // Now do the same as above but with a layer that updates the version to 1.1 on behalf of the application
3141 InstWrapper instance(env.vulkan_functions);
3142 instance.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
3143 instance.CheckCreate();
3144 DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
3145 CreateDebugUtilsMessenger(log);
3146 PFN_vkGetPhysicalDeviceExternalFenceProperties GetPhysicalDeviceExternalFenceProperties =
3147 instance.load("vkGetPhysicalDeviceExternalFenceProperties");
3148 ASSERT_NE(GetPhysicalDeviceExternalFenceProperties, nullptr);
3149
3150 uint32_t driver_count = 1;
3151 VkPhysicalDevice physical_device;
3152 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
3153 ASSERT_EQ(driver_count, 1U);
3154
3155 VkPhysicalDeviceExternalFenceInfo info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO};
3156 VkExternalFenceProperties props{VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES};
3157 GetPhysicalDeviceExternalFenceProperties(physical_device, &info, &props);
3158 ASSERT_TRUE(CompareExtFenceData(env.get_test_icd(0).physical_devices.back().external_fence_properties, props));
3159 ASSERT_FALSE(log.find("Emulating call in ICD"));
3160 }
3161 }
3162 // Test vkGetPhysicalDeviceExternalFenceProperties where instance supports it with some ICDs that both support
3163 // and don't support it:
3164 // ICD 0 supports
3165 // Physical device 0 does not
3166 // Physical device 1 does
3167 // Physical device 2 does not
3168 // ICD 1 doesn't support
3169 // Physical device 3 does not
3170 // ICD 2 supports
3171 // Physical device 4 does not
3172 // Physical device 5 does not
3173 // ICD 3 supports
3174 // Physical device 6 does
TEST(LoaderInstPhysDevExts, PhysDevExtFencePropsMixed)3175 TEST(LoaderInstPhysDevExts, PhysDevExtFencePropsMixed) {
3176 FrameworkEnvironment env{};
3177 const uint32_t max_icd_count = 4;
3178 const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
3179 const uint32_t max_phys_devs = 7;
3180
3181 for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
3182 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, icd != 1 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0));
3183 auto& cur_icd = env.get_test_icd(icd);
3184
3185 // ICD 1 should not have 1.1
3186 if (icd != 1) {
3187 cur_icd.icd_api_version = VK_API_VERSION_1_1;
3188 cur_icd.add_instance_extension({VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME});
3189 }
3190
3191 uint32_t rand_vendor_id;
3192 uint32_t rand_driver_vers;
3193 FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
3194
3195 for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
3196 uint32_t device_version = VK_API_VERSION_1_0;
3197 cur_icd.physical_devices.push_back({});
3198 auto& cur_dev = cur_icd.physical_devices.back();
3199
3200 // 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
3201 if ((icd == 0 && dev == 1) || icd == 3) {
3202 cur_dev.extensions.push_back({VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME, 0});
3203 device_version = VK_API_VERSION_1_1;
3204 }
3205
3206 // Still set physical device properties (so we can determine if device is correct API version)
3207 FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
3208 FillInRandomExtFenceData(cur_dev.external_fence_properties);
3209 }
3210 }
3211
3212 InstWrapper instance(env.vulkan_functions);
3213 instance.create_info.set_api_version(VK_API_VERSION_1_1);
3214 instance.CheckCreate();
3215
3216 PFN_vkGetPhysicalDeviceExternalFenceProperties GetPhysicalDeviceExternalFenceProperties =
3217 instance.load("vkGetPhysicalDeviceExternalFenceProperties");
3218 ASSERT_NE(GetPhysicalDeviceExternalFenceProperties, nullptr);
3219
3220 uint32_t device_count = max_phys_devs;
3221 std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
3222 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
3223 ASSERT_EQ(device_count, max_phys_devs);
3224
3225 for (uint32_t dev = 0; dev < device_count; ++dev) {
3226 VkPhysicalDeviceProperties pd_props{};
3227 instance->vkGetPhysicalDeviceProperties(physical_devices[dev], &pd_props);
3228
3229 for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
3230 auto& cur_icd = env.get_test_icd(icd);
3231 bool found = false;
3232 for (uint32_t pd = 0; pd < dev_counts[icd]; ++pd) {
3233 auto& cur_dev = cur_icd.physical_devices[pd];
3234 // Find the ICD device matching the physical device we're looking at info for so we can compare the
3235 // physical devices info with the returned info.
3236 if (cur_dev.properties.apiVersion == pd_props.apiVersion && cur_dev.properties.deviceID == pd_props.deviceID &&
3237 cur_dev.properties.deviceType == pd_props.deviceType &&
3238 cur_dev.properties.driverVersion == pd_props.driverVersion &&
3239 cur_dev.properties.vendorID == pd_props.vendorID) {
3240 VkPhysicalDeviceExternalFenceInfo info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO};
3241 VkExternalFenceProperties props{VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES};
3242 GetPhysicalDeviceExternalFenceProperties(physical_devices[dev], &info, &props);
3243 // No driver support for extension or 1.1 for ICD 1, all others support
3244 ASSERT_TRUE(CompareExtFenceData(cur_dev.external_fence_properties, props, icd != 1));
3245 found = true;
3246 break;
3247 }
3248 }
3249 if (found) {
3250 break;
3251 }
3252 }
3253 }
3254 }
3255
3256 //
3257 // VK_KHR_get_surface_capabilities2
3258 //
3259
3260 // Test vkGetPhysicalDeviceSurfaceCapabilities2KHR where nothing supports it.
TEST(LoaderInstPhysDevExts, PhysDevSurfaceCaps2KHRNoSupport)3261 TEST(LoaderInstPhysDevExts, PhysDevSurfaceCaps2KHRNoSupport) {
3262 FrameworkEnvironment env{};
3263 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
3264 env.get_test_icd(0).physical_devices.push_back({});
3265
3266 InstWrapper instance(env.vulkan_functions);
3267 instance.CheckCreate();
3268
3269 PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR GetPhysicalDeviceSurfaceCapabilities2KHR =
3270 instance.load("vkGetPhysicalDeviceSurfaceCapabilities2KHR");
3271 ASSERT_EQ(GetPhysicalDeviceSurfaceCapabilities2KHR, nullptr);
3272 }
3273
3274 // Test vkGetPhysicalDeviceSurfaceCapabilities2KHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevSurfaceCaps2KHRNoICDSupport)3275 TEST(LoaderInstPhysDevExts, PhysDevSurfaceCaps2KHRNoICDSupport) {
3276 FrameworkEnvironment env{};
3277 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
3278 env.get_test_icd(0).physical_devices.push_back({});
3279
3280 InstWrapper instance(env.vulkan_functions);
3281 instance.create_info.add_extension(VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME);
3282 instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
3283
3284 PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR GetPhysicalDeviceSurfaceCapabilities2KHR =
3285 instance.load("vkGetPhysicalDeviceSurfaceCapabilities2KHR");
3286 ASSERT_EQ(GetPhysicalDeviceSurfaceCapabilities2KHR, nullptr);
3287 }
3288
3289 // Fill in random but valid data into the surface capability data struct for the current physical device
FillInRandomSurfaceCapsData(VkSurfaceCapabilitiesKHR& props)3290 void FillInRandomSurfaceCapsData(VkSurfaceCapabilitiesKHR& props) {
3291 props.minImageCount = (rand() % 0xFFF) + 1;
3292 props.maxImageCount = (rand() % 0xFFF) + 1;
3293 props.currentExtent.width = (rand() % 0xFFF) + 1;
3294 props.currentExtent.height = (rand() % 0xFFF) + 1;
3295 props.minImageExtent.width = (rand() % 0xFFF) + 1;
3296 props.minImageExtent.height = (rand() % 0xFFF) + 1;
3297 props.maxImageExtent.width = (rand() % 0xFFF) + 1;
3298 props.maxImageExtent.height = (rand() % 0xFFF) + 1;
3299 props.maxImageArrayLayers = (rand() % 0xFFF) + 1;
3300 props.supportedTransforms = static_cast<VkSurfaceTransformFlagsKHR>((rand() % 0xFFF) + 1);
3301 props.currentTransform = static_cast<VkSurfaceTransformFlagBitsKHR>((rand() % 0xFFF) + 1);
3302 props.supportedCompositeAlpha = static_cast<VkCompositeAlphaFlagsKHR>((rand() % 0xFFF) + 1);
3303 props.supportedUsageFlags = static_cast<VkImageUsageFlags>((rand() % 0xFFF) + 1);
3304 }
3305
3306 // Compare the surface capability data structs
CompareSurfaceCapsData(const VkSurfaceCapabilitiesKHR& props1, const VkSurfaceCapabilitiesKHR& props2, bool supported = true)3307 bool CompareSurfaceCapsData(const VkSurfaceCapabilitiesKHR& props1, const VkSurfaceCapabilitiesKHR& props2, bool supported = true) {
3308 bool equal = true;
3309 if (supported) {
3310 equal = equal && props1.minImageCount == props2.minImageCount;
3311 equal = equal && props1.maxImageCount == props2.maxImageCount;
3312 equal = equal && props1.currentExtent.width == props2.currentExtent.width;
3313 equal = equal && props1.currentExtent.height == props2.currentExtent.height;
3314 equal = equal && props1.minImageExtent.width == props2.minImageExtent.width;
3315 equal = equal && props1.minImageExtent.height == props2.minImageExtent.height;
3316 equal = equal && props1.maxImageExtent.width == props2.maxImageExtent.width;
3317 equal = equal && props1.maxImageExtent.height == props2.maxImageExtent.height;
3318 equal = equal && props1.maxImageArrayLayers == props2.maxImageArrayLayers;
3319 equal = equal && props1.supportedTransforms == props2.supportedTransforms;
3320 equal = equal && props1.currentTransform == props2.currentTransform;
3321 equal = equal && props1.supportedCompositeAlpha == props2.supportedCompositeAlpha;
3322 equal = equal && props1.supportedUsageFlags == props2.supportedUsageFlags;
3323 } else {
3324 equal = equal && 0 == props2.minImageCount;
3325 equal = equal && 0 == props2.maxImageCount;
3326 equal = equal && 0 == props2.currentExtent.width;
3327 equal = equal && 0 == props2.currentExtent.height;
3328 equal = equal && 0 == props2.minImageExtent.width;
3329 equal = equal && 0 == props2.minImageExtent.height;
3330 equal = equal && 0 == props2.maxImageExtent.width;
3331 equal = equal && 0 == props2.maxImageExtent.height;
3332 equal = equal && 0 == props2.maxImageArrayLayers;
3333 equal = equal && 0 == props2.supportedTransforms;
3334 equal = equal && 0 == props2.currentTransform;
3335 equal = equal && 0 == props2.supportedCompositeAlpha;
3336 equal = equal && 0 == props2.supportedUsageFlags;
3337 }
3338 return equal;
3339 }
3340
3341 // Test vkGetPhysicalDeviceSurfaceCapabilities2KHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, PhysDevSurfaceCaps2KHRInstanceAndICDSupport)3342 TEST(LoaderInstPhysDevExts, PhysDevSurfaceCaps2KHRInstanceAndICDSupport) {
3343 FrameworkEnvironment env{};
3344 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
3345 Extension first_ext{VK_KHR_SURFACE_EXTENSION_NAME};
3346 Extension second_ext{VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME};
3347 Extension third_ext{VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME};
3348 auto& cur_icd = env.get_test_icd(0);
3349 cur_icd.add_instance_extensions({first_ext, second_ext, third_ext});
3350 cur_icd.physical_devices.push_back({});
3351 cur_icd.min_icd_interface_version = 3;
3352 cur_icd.enable_icd_wsi = true;
3353 FillInRandomSurfaceCapsData(env.get_test_icd(0).physical_devices.back().surface_capabilities);
3354
3355 InstWrapper instance(env.vulkan_functions);
3356 instance.create_info.add_extensions(
3357 {VK_KHR_SURFACE_EXTENSION_NAME, VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME, VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME});
3358 instance.CheckCreate();
3359
3360 PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR GetPhysicalDeviceSurfaceCapabilitiesKHR =
3361 instance.load("vkGetPhysicalDeviceSurfaceCapabilitiesKHR");
3362 ASSERT_NE(GetPhysicalDeviceSurfaceCapabilitiesKHR, nullptr);
3363 PFN_vkCreateHeadlessSurfaceEXT CreateHeadlessSurfaceEXT = instance.load("vkCreateHeadlessSurfaceEXT");
3364 ASSERT_NE(CreateHeadlessSurfaceEXT, nullptr);
3365 PFN_vkDestroySurfaceKHR DestroySurfaceKHR = instance.load("vkDestroySurfaceKHR");
3366 ASSERT_NE(DestroySurfaceKHR, nullptr);
3367 PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR GetPhysicalDeviceSurfaceCapabilities2KHR =
3368 instance.load("vkGetPhysicalDeviceSurfaceCapabilities2KHR");
3369 ASSERT_NE(GetPhysicalDeviceSurfaceCapabilities2KHR, nullptr);
3370
3371 uint32_t driver_count = 1;
3372 VkPhysicalDevice physical_device;
3373 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
3374 ASSERT_EQ(driver_count, 1U);
3375
3376 VkSurfaceKHR surface;
3377 VkHeadlessSurfaceCreateInfoEXT create_info{VK_STRUCTURE_TYPE_HEADLESS_SURFACE_CREATE_INFO_EXT};
3378 ASSERT_EQ(VK_SUCCESS, CreateHeadlessSurfaceEXT(instance.inst, &create_info, nullptr, &surface));
3379
3380 VkSurfaceCapabilitiesKHR props{};
3381 ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, surface, &props));
3382
3383 VkPhysicalDeviceSurfaceInfo2KHR info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR, nullptr, surface};
3384 VkSurfaceCapabilities2KHR props2{VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR};
3385 ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceSurfaceCapabilities2KHR(physical_device, &info, &props2));
3386 ASSERT_TRUE(CompareSurfaceCapsData(props, props2.surfaceCapabilities));
3387
3388 DestroySurfaceKHR(instance.inst, surface, nullptr);
3389 }
3390
3391 // Test vkGetPhysicalDeviceSurfaceCapabilities2 where instance supports it with some ICDs that both support
3392 // and don't support it:
3393 // ICD 0 supports
3394 // Physical device 0 does not
3395 // Physical device 1 does
3396 // Physical device 2 does not
3397 // ICD 1 doesn't support
3398 // Physical device 3 does not
3399 // ICD 2 supports
3400 // Physical device 4 does not
3401 // Physical device 5 does not
3402 // ICD 3 supports
3403 // Physical device 6 does
TEST(LoaderInstPhysDevExts, PhysDevSurfaceCaps2KHRMixed)3404 TEST(LoaderInstPhysDevExts, PhysDevSurfaceCaps2KHRMixed) {
3405 FrameworkEnvironment env{};
3406 const uint32_t max_icd_count = 4;
3407 const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
3408 const uint32_t max_phys_devs = 7;
3409 Extension first_ext{VK_KHR_SURFACE_EXTENSION_NAME};
3410 Extension second_ext{VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME};
3411 Extension third_ext{VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME};
3412
3413 for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
3414 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, icd != 1 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0));
3415 auto& cur_icd = env.get_test_icd(icd);
3416 cur_icd.icd_api_version = VK_API_VERSION_1_0;
3417 cur_icd.min_icd_interface_version = 3;
3418 cur_icd.enable_icd_wsi = true;
3419 cur_icd.add_instance_extensions({first_ext, third_ext});
3420
3421 // ICD 1 should not have 1.1
3422 if (icd != 1) {
3423 cur_icd.icd_api_version = VK_API_VERSION_1_1;
3424 cur_icd.add_instance_extension(second_ext);
3425 }
3426
3427 uint32_t rand_vendor_id;
3428 uint32_t rand_driver_vers;
3429 FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
3430
3431 for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
3432 uint32_t device_version = VK_API_VERSION_1_0;
3433 cur_icd.physical_devices.push_back({});
3434 auto& cur_dev = cur_icd.physical_devices.back();
3435 cur_dev.extensions.push_back({VK_KHR_SURFACE_EXTENSION_NAME, 0});
3436 cur_dev.extensions.push_back({VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME, 0});
3437
3438 // 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
3439 if ((icd == 0 && dev == 1) || icd == 3) {
3440 cur_dev.extensions.push_back({VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME, 0});
3441 device_version = VK_API_VERSION_1_1;
3442 }
3443
3444 // Still set physical device properties (so we can determine if device is correct API version)
3445 FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
3446 FillInRandomSurfaceCapsData(cur_dev.surface_capabilities);
3447 }
3448 }
3449
3450 InstWrapper instance(env.vulkan_functions);
3451 instance.create_info.add_extensions(
3452 {VK_KHR_SURFACE_EXTENSION_NAME, VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME, VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME});
3453 instance.CheckCreate();
3454
3455 PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR GetPhysicalDeviceSurfaceCapabilitiesKHR =
3456 instance.load("vkGetPhysicalDeviceSurfaceCapabilitiesKHR");
3457 ASSERT_NE(GetPhysicalDeviceSurfaceCapabilitiesKHR, nullptr);
3458 PFN_vkCreateHeadlessSurfaceEXT CreateHeadlessSurfaceEXT = instance.load("vkCreateHeadlessSurfaceEXT");
3459 ASSERT_NE(CreateHeadlessSurfaceEXT, nullptr);
3460 PFN_vkDestroySurfaceKHR DestroySurfaceKHR = instance.load("vkDestroySurfaceKHR");
3461 ASSERT_NE(DestroySurfaceKHR, nullptr);
3462 PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR GetPhysicalDeviceSurfaceCapabilities2KHR =
3463 instance.load("vkGetPhysicalDeviceSurfaceCapabilities2KHR");
3464 ASSERT_NE(GetPhysicalDeviceSurfaceCapabilities2KHR, nullptr);
3465
3466 uint32_t device_count = max_phys_devs;
3467 std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
3468 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
3469 ASSERT_EQ(device_count, max_phys_devs);
3470
3471 VkSurfaceKHR surface;
3472 VkHeadlessSurfaceCreateInfoEXT create_info{VK_STRUCTURE_TYPE_HEADLESS_SURFACE_CREATE_INFO_EXT};
3473 ASSERT_EQ(VK_SUCCESS, CreateHeadlessSurfaceEXT(instance.inst, &create_info, nullptr, &surface));
3474
3475 for (uint32_t dev = 0; dev < device_count; ++dev) {
3476 VkSurfaceCapabilitiesKHR props{};
3477 ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceSurfaceCapabilitiesKHR(physical_devices[dev], surface, &props));
3478
3479 VkPhysicalDeviceSurfaceInfo2KHR info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR, nullptr, surface};
3480 VkSurfaceCapabilities2KHR props2{VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR};
3481 ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceSurfaceCapabilities2KHR(physical_devices[dev], &info, &props2));
3482 ASSERT_TRUE(CompareSurfaceCapsData(props, props2.surfaceCapabilities));
3483 }
3484
3485 DestroySurfaceKHR(instance.inst, surface, nullptr);
3486 }
3487
3488 // Test vkGetPhysicalDeviceSurfaceFormats2KHR where nothing supports it.
TEST(LoaderInstPhysDevExts, PhysDevSurfaceFormats2KHRNoSupport)3489 TEST(LoaderInstPhysDevExts, PhysDevSurfaceFormats2KHRNoSupport) {
3490 FrameworkEnvironment env{};
3491 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
3492 env.get_test_icd(0).physical_devices.push_back({});
3493
3494 InstWrapper instance(env.vulkan_functions);
3495 instance.CheckCreate();
3496
3497 PFN_vkGetPhysicalDeviceSurfaceFormats2KHR GetPhysicalDeviceSurfaceFormats2KHR =
3498 instance.load("vkGetPhysicalDeviceSurfaceFormats2KHR");
3499 ASSERT_EQ(GetPhysicalDeviceSurfaceFormats2KHR, nullptr);
3500 }
3501
3502 // Test vkGetPhysicalDeviceSurfaceFormats2KHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevSurfaceFormats2KHRNoICDSupport)3503 TEST(LoaderInstPhysDevExts, PhysDevSurfaceFormats2KHRNoICDSupport) {
3504 FrameworkEnvironment env{};
3505 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
3506 env.get_test_icd(0).physical_devices.push_back({});
3507
3508 InstWrapper instance(env.vulkan_functions);
3509 instance.create_info.add_extension(VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME);
3510 instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
3511
3512 PFN_vkGetPhysicalDeviceSurfaceFormats2KHR GetPhysicalDeviceSurfaceFormats2KHR =
3513 instance.load("vkGetPhysicalDeviceSurfaceFormats2KHR");
3514 ASSERT_EQ(GetPhysicalDeviceSurfaceFormats2KHR, nullptr);
3515 }
3516
3517 // Fill in random but valid data into the surface formats data struct for the current physical device
FillInRandomSurfaceFormatsData(std::vector<VkSurfaceFormatKHR>& props)3518 void FillInRandomSurfaceFormatsData(std::vector<VkSurfaceFormatKHR>& props) {
3519 props.resize((rand() % 5) + 1);
3520 for (uint32_t i = 0; i < props.size(); ++i) {
3521 props[i].format = static_cast<VkFormat>((rand() % 0xFFF) + 1);
3522 props[i].colorSpace = static_cast<VkColorSpaceKHR>((rand() % 0xFFF) + 1);
3523 }
3524 }
3525
3526 // Compare the surface formats data structs
CompareSurfaceFormatsData(const std::vector<VkSurfaceFormatKHR>& props1, const std::vector<VkSurfaceFormat2KHR>& props2, bool supported = true)3527 bool CompareSurfaceFormatsData(const std::vector<VkSurfaceFormatKHR>& props1, const std::vector<VkSurfaceFormat2KHR>& props2,
3528 bool supported = true) {
3529 if (props1.size() != props2.size()) return false;
3530 bool equal = true;
3531 for (uint32_t i = 0; i < props1.size(); ++i) {
3532 if (supported) {
3533 equal = equal && props1[i].format == props2[i].surfaceFormat.format;
3534 equal = equal && props1[i].colorSpace == props2[i].surfaceFormat.colorSpace;
3535 } else {
3536 equal = equal && 0 == props2[i].surfaceFormat.format;
3537 equal = equal && 0 == props2[i].surfaceFormat.colorSpace;
3538 }
3539 }
3540 return equal;
3541 }
3542
3543 // Test vkGetPhysicalDeviceSurfaceFormats2KHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, PhysDevSurfaceFormats2KHRInstanceAndICDSupport)3544 TEST(LoaderInstPhysDevExts, PhysDevSurfaceFormats2KHRInstanceAndICDSupport) {
3545 FrameworkEnvironment env{};
3546 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
3547 Extension first_ext{VK_KHR_SURFACE_EXTENSION_NAME};
3548 Extension second_ext{VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME};
3549 Extension third_ext{VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME};
3550 auto& cur_icd = env.get_test_icd(0);
3551 cur_icd.add_instance_extensions({first_ext, second_ext, third_ext});
3552 cur_icd.physical_devices.push_back({});
3553 cur_icd.min_icd_interface_version = 3;
3554 cur_icd.enable_icd_wsi = true;
3555 FillInRandomSurfaceFormatsData(env.get_test_icd(0).physical_devices.back().surface_formats);
3556
3557 InstWrapper instance(env.vulkan_functions);
3558 instance.create_info.add_extensions(
3559 {VK_KHR_SURFACE_EXTENSION_NAME, VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME, VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME});
3560 instance.CheckCreate();
3561
3562 PFN_vkGetPhysicalDeviceSurfaceFormatsKHR GetPhysicalDeviceSurfaceFormatsKHR =
3563 instance.load("vkGetPhysicalDeviceSurfaceFormatsKHR");
3564 ASSERT_NE(GetPhysicalDeviceSurfaceFormatsKHR, nullptr);
3565 PFN_vkCreateHeadlessSurfaceEXT CreateHeadlessSurfaceEXT = instance.load("vkCreateHeadlessSurfaceEXT");
3566 ASSERT_NE(CreateHeadlessSurfaceEXT, nullptr);
3567 PFN_vkDestroySurfaceKHR DestroySurfaceKHR = instance.load("vkDestroySurfaceKHR");
3568 ASSERT_NE(DestroySurfaceKHR, nullptr);
3569 PFN_vkGetPhysicalDeviceSurfaceFormats2KHR GetPhysicalDeviceSurfaceFormats2KHR =
3570 instance.load("vkGetPhysicalDeviceSurfaceFormats2KHR");
3571 ASSERT_NE(GetPhysicalDeviceSurfaceFormats2KHR, nullptr);
3572
3573 uint32_t driver_count = 1;
3574 VkPhysicalDevice physical_device;
3575 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
3576 ASSERT_EQ(driver_count, 1U);
3577
3578 VkSurfaceKHR surface;
3579 VkHeadlessSurfaceCreateInfoEXT create_info{VK_STRUCTURE_TYPE_HEADLESS_SURFACE_CREATE_INFO_EXT};
3580 ASSERT_EQ(VK_SUCCESS, CreateHeadlessSurfaceEXT(instance.inst, &create_info, nullptr, &surface));
3581
3582 std::vector<VkSurfaceFormatKHR> props{};
3583 uint32_t count_1 = 0;
3584 ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &count_1, nullptr));
3585 ASSERT_EQ(env.get_test_icd(0).physical_devices.back().surface_formats.size(), count_1);
3586 props.resize(count_1);
3587 ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &count_1, props.data()));
3588 ASSERT_EQ(env.get_test_icd(0).physical_devices.back().surface_formats.size(), count_1);
3589
3590 VkPhysicalDeviceSurfaceInfo2KHR info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR, nullptr, surface};
3591 std::vector<VkSurfaceFormat2KHR> props2{};
3592 uint32_t count_2 = 0;
3593 ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceSurfaceFormats2KHR(physical_device, &info, &count_2, nullptr));
3594 ASSERT_EQ(count_1, count_2);
3595 props2.resize(count_2, VkSurfaceFormat2KHR{VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR});
3596 ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceSurfaceFormats2KHR(physical_device, &info, &count_2, props2.data()));
3597 ASSERT_TRUE(CompareSurfaceFormatsData(props, props2));
3598
3599 DestroySurfaceKHR(instance.inst, surface, nullptr);
3600 }
3601
3602 // Test vkGetPhysicalDeviceSurfaceFormats2 where instance supports it with some ICDs that both support
3603 // and don't support it:
3604 // ICD 0 supports
3605 // Physical device 0 does not
3606 // Physical device 1 does
3607 // Physical device 2 does not
3608 // ICD 1 doesn't support
3609 // Physical device 3 does not
3610 // ICD 2 supports
3611 // Physical device 4 does not
3612 // Physical device 5 does not
3613 // ICD 3 supports
3614 // Physical device 6 does
TEST(LoaderInstPhysDevExts, PhysDevSurfaceFormats2KHRMixed)3615 TEST(LoaderInstPhysDevExts, PhysDevSurfaceFormats2KHRMixed) {
3616 FrameworkEnvironment env{};
3617 const uint32_t max_icd_count = 4;
3618 const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
3619 const uint32_t max_phys_devs = 7;
3620 Extension first_ext{VK_KHR_SURFACE_EXTENSION_NAME};
3621 Extension second_ext{VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME};
3622 Extension third_ext{VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME};
3623
3624 for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
3625 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, icd != 1 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0));
3626 auto& cur_icd = env.get_test_icd(icd);
3627 cur_icd.icd_api_version = VK_API_VERSION_1_0;
3628 cur_icd.enable_icd_wsi = true;
3629 cur_icd.min_icd_interface_version = 3;
3630 cur_icd.add_instance_extensions({first_ext, third_ext});
3631
3632 // ICD 1 should not have 1.1
3633 if (icd != 1) {
3634 cur_icd.icd_api_version = VK_API_VERSION_1_1;
3635 cur_icd.add_instance_extension(second_ext);
3636 }
3637
3638 uint32_t rand_vendor_id;
3639 uint32_t rand_driver_vers;
3640 FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
3641
3642 for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
3643 uint32_t device_version = VK_API_VERSION_1_0;
3644 cur_icd.physical_devices.push_back({});
3645 auto& cur_dev = cur_icd.physical_devices.back();
3646 cur_dev.extensions.push_back({VK_KHR_SURFACE_EXTENSION_NAME, 0});
3647 cur_dev.extensions.push_back({VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME, 0});
3648
3649 // 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
3650 if ((icd == 0 && dev == 1) || icd == 3) {
3651 cur_dev.extensions.push_back({VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME, 0});
3652 device_version = VK_API_VERSION_1_1;
3653 }
3654
3655 // Still set physical device properties (so we can determine if device is correct API version)
3656 FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
3657 FillInRandomSurfaceFormatsData(cur_dev.surface_formats);
3658 }
3659 }
3660
3661 InstWrapper instance(env.vulkan_functions);
3662 instance.create_info.add_extensions(
3663 {VK_KHR_SURFACE_EXTENSION_NAME, VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME, VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME});
3664 instance.CheckCreate();
3665
3666 PFN_vkGetPhysicalDeviceSurfaceFormatsKHR GetPhysicalDeviceSurfaceFormatsKHR =
3667 instance.load("vkGetPhysicalDeviceSurfaceFormatsKHR");
3668 ASSERT_NE(GetPhysicalDeviceSurfaceFormatsKHR, nullptr);
3669 PFN_vkCreateHeadlessSurfaceEXT CreateHeadlessSurfaceEXT = instance.load("vkCreateHeadlessSurfaceEXT");
3670 ASSERT_NE(CreateHeadlessSurfaceEXT, nullptr);
3671 PFN_vkDestroySurfaceKHR DestroySurfaceKHR = instance.load("vkDestroySurfaceKHR");
3672 ASSERT_NE(DestroySurfaceKHR, nullptr);
3673 PFN_vkGetPhysicalDeviceSurfaceFormats2KHR GetPhysicalDeviceSurfaceFormats2KHR =
3674 instance.load("vkGetPhysicalDeviceSurfaceFormats2KHR");
3675 ASSERT_NE(GetPhysicalDeviceSurfaceFormats2KHR, nullptr);
3676
3677 uint32_t device_count = max_phys_devs;
3678 std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
3679 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
3680 ASSERT_EQ(device_count, max_phys_devs);
3681
3682 VkSurfaceKHR surface;
3683 VkHeadlessSurfaceCreateInfoEXT create_info{VK_STRUCTURE_TYPE_HEADLESS_SURFACE_CREATE_INFO_EXT};
3684 ASSERT_EQ(VK_SUCCESS, CreateHeadlessSurfaceEXT(instance.inst, &create_info, nullptr, &surface));
3685
3686 for (uint32_t dev = 0; dev < device_count; ++dev) {
3687 std::vector<VkSurfaceFormatKHR> props{};
3688 uint32_t count_1 = 0;
3689 ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceSurfaceFormatsKHR(physical_devices[dev], surface, &count_1, nullptr));
3690 ASSERT_NE(0U, count_1);
3691 props.resize(count_1);
3692 ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceSurfaceFormatsKHR(physical_devices[dev], surface, &count_1, props.data()));
3693 ASSERT_NE(0U, count_1);
3694
3695 VkPhysicalDeviceSurfaceInfo2KHR info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR, nullptr, surface};
3696 std::vector<VkSurfaceFormat2KHR> props2{};
3697 uint32_t count_2 = 0;
3698 ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceSurfaceFormats2KHR(physical_devices[dev], &info, &count_2, nullptr));
3699 ASSERT_EQ(count_1, count_2);
3700 props2.resize(count_2, VkSurfaceFormat2KHR{VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR});
3701 ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceSurfaceFormats2KHR(physical_devices[dev], &info, &count_2, props2.data()));
3702 ASSERT_EQ(count_1, count_2);
3703 ASSERT_TRUE(CompareSurfaceFormatsData(props, props2));
3704 }
3705
3706 DestroySurfaceKHR(instance.inst, surface, nullptr);
3707 }
3708
3709 //
3710 // VK_KHR_display
3711 //
3712
3713 // Test vkGetPhysicalDeviceDisplayPropertiesKHR where nothing supports it.
TEST(LoaderInstPhysDevExts, PhysDevDispPropsKHRNoSupport)3714 TEST(LoaderInstPhysDevExts, PhysDevDispPropsKHRNoSupport) {
3715 FrameworkEnvironment env{};
3716 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
3717 env.get_test_icd(0).physical_devices.push_back({});
3718
3719 InstWrapper instance(env.vulkan_functions);
3720 instance.CheckCreate();
3721
3722 PFN_vkGetPhysicalDeviceDisplayPropertiesKHR GetPhysicalDeviceDisplayPropertiesKHR =
3723 instance.load("vkGetPhysicalDeviceDisplayPropertiesKHR");
3724 ASSERT_EQ(GetPhysicalDeviceDisplayPropertiesKHR, nullptr);
3725 }
3726
3727 // Test vkGetPhysicalDeviceDisplayPropertiesKHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevDispPropsKHRNoICDSupport)3728 TEST(LoaderInstPhysDevExts, PhysDevDispPropsKHRNoICDSupport) {
3729 FrameworkEnvironment env{};
3730 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
3731 env.get_test_icd(0).physical_devices.push_back({});
3732
3733 InstWrapper instance(env.vulkan_functions);
3734 instance.create_info.add_extension(VK_KHR_DISPLAY_EXTENSION_NAME);
3735 instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
3736
3737 PFN_vkGetPhysicalDeviceDisplayPropertiesKHR GetPhysicalDeviceDisplayPropertiesKHR =
3738 instance.load("vkGetPhysicalDeviceDisplayPropertiesKHR");
3739 ASSERT_EQ(GetPhysicalDeviceDisplayPropertiesKHR, nullptr);
3740 }
3741
CreateRandomDisplay()3742 VkDisplayKHR CreateRandomDisplay() { return (VkDisplayKHR)(((rand() % 0xFFFFFFFBull) << 12) * (rand() % 0xFFFFFFFull) + 1); }
3743
CreateRandomDisplayMode()3744 VkDisplayModeKHR CreateRandomDisplayMode() {
3745 return (VkDisplayModeKHR)(((rand() % 0xFFFFFFFBull) << 12) * (rand() % 0xFFFFFFFull) + 1);
3746 }
3747
3748 // Fill in random but valid data into the display property data struct for the current physical device
FillInRandomDisplayPropData(std::vector<VkDisplayPropertiesKHR>& props)3749 void FillInRandomDisplayPropData(std::vector<VkDisplayPropertiesKHR>& props) {
3750 props.resize((rand() % 5) + 1);
3751 for (uint32_t i = 0; i < props.size(); ++i) {
3752 props[i].display = CreateRandomDisplay();
3753 props[i].physicalDimensions.width = static_cast<uint32_t>((rand() % 0xFFF) + 1);
3754 props[i].physicalDimensions.height = static_cast<uint32_t>((rand() % 0xFFF) + 1);
3755 props[i].physicalResolution.width = static_cast<uint32_t>((rand() % 0xFFF) + 1);
3756 props[i].physicalResolution.height = static_cast<uint32_t>((rand() % 0xFFF) + 1);
3757 props[i].supportedTransforms = static_cast<VkSurfaceTransformFlagsKHR>((rand() % 0xFFE) + 1);
3758 props[i].planeReorderPossible = rand() % 2 > 0 ? VK_TRUE : VK_FALSE;
3759 props[i].persistentContent = rand() % 2 > 0 ? VK_TRUE : VK_FALSE;
3760 }
3761 }
3762
3763 // Compare the display property data structs
CompareDisplayPropData(const std::vector<VkDisplayPropertiesKHR>& props1, const std::vector<VkDisplayPropertiesKHR>& props2)3764 bool CompareDisplayPropData(const std::vector<VkDisplayPropertiesKHR>& props1, const std::vector<VkDisplayPropertiesKHR>& props2) {
3765 if (props1.size() != props2.size()) return false;
3766 bool equal = true;
3767 for (uint32_t i = 0; i < props1.size(); ++i) {
3768 equal = equal && props1[i].display == props2[i].display;
3769 equal = equal && props1[i].physicalDimensions.width == props2[i].physicalDimensions.width;
3770 equal = equal && props1[i].physicalDimensions.height == props2[i].physicalDimensions.height;
3771 equal = equal && props1[i].physicalResolution.width == props2[i].physicalResolution.width;
3772 equal = equal && props1[i].physicalResolution.height == props2[i].physicalResolution.height;
3773 equal = equal && props1[i].supportedTransforms == props2[i].supportedTransforms;
3774 equal = equal && props1[i].planeReorderPossible == props2[i].planeReorderPossible;
3775 equal = equal && props1[i].persistentContent == props2[i].persistentContent;
3776 }
3777 return equal;
3778 }
3779
3780 // Test vGetPhysicalDeviceDisplayPropertiesKHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, PhysDevDispPropsKHRInstanceAndICDSupport)3781 TEST(LoaderInstPhysDevExts, PhysDevDispPropsKHRInstanceAndICDSupport) {
3782 FrameworkEnvironment env{};
3783 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
3784 env.get_test_icd(0).add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
3785 env.get_test_icd(0).physical_devices.push_back({});
3786 FillInRandomDisplayPropData(env.get_test_icd(0).physical_devices.back().display_properties);
3787
3788 InstWrapper instance(env.vulkan_functions);
3789 instance.create_info.add_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
3790 instance.CheckCreate();
3791
3792 PFN_vkGetPhysicalDeviceDisplayPropertiesKHR GetPhysicalDeviceDisplayPropertiesKHR =
3793 instance.load("vkGetPhysicalDeviceDisplayPropertiesKHR");
3794 ASSERT_NE(GetPhysicalDeviceDisplayPropertiesKHR, nullptr);
3795
3796 uint32_t driver_count = 1;
3797 VkPhysicalDevice physical_device;
3798 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
3799 ASSERT_EQ(driver_count, 1U);
3800
3801 std::vector<VkDisplayPropertiesKHR> props{};
3802 uint32_t prop_count = 0;
3803 ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayPropertiesKHR(physical_device, &prop_count, nullptr));
3804 ASSERT_EQ(env.get_test_icd(0).physical_devices.back().display_properties.size(), prop_count);
3805 props.resize(prop_count);
3806 ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayPropertiesKHR(physical_device, &prop_count, props.data()));
3807 ASSERT_EQ(env.get_test_icd(0).physical_devices.back().display_properties.size(), prop_count);
3808
3809 ASSERT_TRUE(CompareDisplayPropData(props, env.get_test_icd(0).physical_devices.back().display_properties));
3810 }
3811
3812 // Test vkGetPhysicalDeviceDisplayPropertiesKHR where instance supports it with some ICDs that both support
3813 // and don't support it:
3814 // ICD 0 supports
3815 // Physical device 0 does not
3816 // Physical device 1 does
3817 // Physical device 2 does not
3818 // ICD 1 doesn't support
3819 // Physical device 3 does not
3820 // ICD 2 supports
3821 // Physical device 4 does not
3822 // Physical device 5 does not
3823 // ICD 3 supports
3824 // Physical device 6 does
TEST(LoaderInstPhysDevExts, PhysDevDispPropsKHRMixed)3825 TEST(LoaderInstPhysDevExts, PhysDevDispPropsKHRMixed) {
3826 FrameworkEnvironment env{};
3827 const uint32_t max_icd_count = 4;
3828 const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
3829 const uint32_t max_phys_devs = 7;
3830
3831 for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
3832 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, icd != 1 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0));
3833 auto& cur_icd = env.get_test_icd(icd);
3834 cur_icd.icd_api_version = VK_API_VERSION_1_0;
3835
3836 // ICD 1 should not have 1.1
3837 if (icd != 1) {
3838 cur_icd.icd_api_version = VK_API_VERSION_1_1;
3839 cur_icd.add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
3840 }
3841
3842 uint32_t rand_vendor_id;
3843 uint32_t rand_driver_vers;
3844 FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
3845
3846 for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
3847 uint32_t device_version = VK_API_VERSION_1_0;
3848 cur_icd.physical_devices.push_back({});
3849 auto& cur_dev = cur_icd.physical_devices.back();
3850
3851 // 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
3852 if ((icd == 0 && dev == 1) || icd == 3) {
3853 cur_dev.extensions.push_back({VK_KHR_DISPLAY_EXTENSION_NAME, 0});
3854 device_version = VK_API_VERSION_1_1;
3855 }
3856
3857 // Still set physical device properties (so we can determine if device is correct API version)
3858 FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
3859 FillInRandomDisplayPropData(cur_dev.display_properties);
3860 }
3861 }
3862
3863 InstWrapper instance(env.vulkan_functions);
3864 instance.create_info.add_extension(VK_KHR_DISPLAY_EXTENSION_NAME);
3865 instance.CheckCreate();
3866
3867 PFN_vkGetPhysicalDeviceDisplayPropertiesKHR GetPhysicalDeviceDisplayPropertiesKHR =
3868 instance.load("vkGetPhysicalDeviceDisplayPropertiesKHR");
3869 ASSERT_NE(GetPhysicalDeviceDisplayPropertiesKHR, nullptr);
3870
3871 uint32_t device_count = max_phys_devs;
3872 std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
3873 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
3874 ASSERT_EQ(device_count, max_phys_devs);
3875
3876 for (uint32_t dev = 0; dev < device_count; ++dev) {
3877 VkPhysicalDeviceProperties pd_props{};
3878 instance->vkGetPhysicalDeviceProperties(physical_devices[dev], &pd_props);
3879
3880 for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
3881 auto& cur_icd = env.get_test_icd(icd);
3882 bool found = false;
3883 for (uint32_t pd = 0; pd < dev_counts[icd]; ++pd) {
3884 auto& cur_dev = cur_icd.physical_devices[pd];
3885 // Find the ICD device matching the physical device we're looking at info for so we can compare the
3886 // physical devices info with the returned info.
3887 if (cur_dev.properties.apiVersion == pd_props.apiVersion && cur_dev.properties.deviceID == pd_props.deviceID &&
3888 cur_dev.properties.deviceType == pd_props.deviceType &&
3889 cur_dev.properties.driverVersion == pd_props.driverVersion &&
3890 cur_dev.properties.vendorID == pd_props.vendorID) {
3891 std::vector<VkDisplayPropertiesKHR> props{};
3892 uint32_t prop_count = 0;
3893 ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayPropertiesKHR(physical_devices[dev], &prop_count, nullptr));
3894 if (icd == 1) {
3895 // For this extension, if no support exists (like for ICD 1), the value of 0 should be returned by the
3896 // loader.
3897 ASSERT_EQ(0U, prop_count);
3898 } else {
3899 ASSERT_EQ(cur_dev.display_properties.size(), prop_count);
3900 props.resize(prop_count);
3901 ASSERT_EQ(VK_SUCCESS,
3902 GetPhysicalDeviceDisplayPropertiesKHR(physical_devices[dev], &prop_count, props.data()));
3903 ASSERT_EQ(cur_dev.display_properties.size(), prop_count);
3904
3905 ASSERT_TRUE(CompareDisplayPropData(props, cur_dev.display_properties));
3906 }
3907 found = true;
3908 break;
3909 }
3910 }
3911 if (found) {
3912 break;
3913 }
3914 }
3915 }
3916 }
3917
3918 // Test vkGetPhysicalDeviceDisplayPlanePropertiesKHR where nothing supports it.
TEST(LoaderInstPhysDevExts, PhysDevDispPlanePropsKHRNoSupport)3919 TEST(LoaderInstPhysDevExts, PhysDevDispPlanePropsKHRNoSupport) {
3920 FrameworkEnvironment env{};
3921 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
3922 env.get_test_icd(0).physical_devices.push_back({});
3923
3924 InstWrapper instance(env.vulkan_functions);
3925 instance.CheckCreate();
3926
3927 PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR GetPhysicalDeviceDisplayPlanePropertiesKHR =
3928 instance.load("vkGetPhysicalDeviceDisplayPlanePropertiesKHR");
3929 ASSERT_EQ(GetPhysicalDeviceDisplayPlanePropertiesKHR, nullptr);
3930 }
3931
3932 // Test vkGetPhysicalDeviceDisplayPlanePropertiesKHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevDispPlanePropsKHRNoICDSupport)3933 TEST(LoaderInstPhysDevExts, PhysDevDispPlanePropsKHRNoICDSupport) {
3934 FrameworkEnvironment env{};
3935 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
3936 env.get_test_icd(0).physical_devices.push_back({});
3937
3938 InstWrapper instance(env.vulkan_functions);
3939 instance.create_info.add_extension(VK_KHR_DISPLAY_EXTENSION_NAME);
3940 instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
3941
3942 PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR GetPhysicalDeviceDisplayPlanePropertiesKHR =
3943 instance.load("vkGetPhysicalDeviceDisplayPlanePropertiesKHR");
3944 ASSERT_EQ(GetPhysicalDeviceDisplayPlanePropertiesKHR, nullptr);
3945 }
3946
3947 // Fill in random but valid data into the display plane property data struct for the current physical device
FillInRandomDisplayPlanePropData(std::vector<VkDisplayPlanePropertiesKHR>& props)3948 void FillInRandomDisplayPlanePropData(std::vector<VkDisplayPlanePropertiesKHR>& props) {
3949 props.resize((rand() % 5) + 1);
3950 for (uint32_t i = 0; i < props.size(); ++i) {
3951 props[i].currentDisplay = CreateRandomDisplay();
3952 props[i].currentStackIndex = static_cast<uint32_t>((rand() % 0xFFF) + (rand() % 0xFFF) + 1);
3953 }
3954 }
3955
3956 // Compare the display plane property data structs
CompareDisplayPlanePropData(const std::vector<VkDisplayPlanePropertiesKHR>& props1, const std::vector<VkDisplayPlanePropertiesKHR>& props2)3957 bool CompareDisplayPlanePropData(const std::vector<VkDisplayPlanePropertiesKHR>& props1,
3958 const std::vector<VkDisplayPlanePropertiesKHR>& props2) {
3959 if (props1.size() != props2.size()) return false;
3960 bool equal = true;
3961 for (uint32_t i = 0; i < props1.size(); ++i) {
3962 equal = equal && props1[i].currentDisplay == props2[i].currentDisplay;
3963 equal = equal && props1[i].currentStackIndex == props2[i].currentStackIndex;
3964 }
3965 return equal;
3966 }
3967
3968 // Test vGetPhysicalDeviceDisplayPlanePropertiesKHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, PhysDevDispPlanePropsKHRInstanceAndICDSupport)3969 TEST(LoaderInstPhysDevExts, PhysDevDispPlanePropsKHRInstanceAndICDSupport) {
3970 FrameworkEnvironment env{};
3971 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
3972 env.get_test_icd(0).add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
3973 env.get_test_icd(0).physical_devices.push_back({});
3974 FillInRandomDisplayPlanePropData(env.get_test_icd(0).physical_devices.back().display_plane_properties);
3975
3976 InstWrapper instance(env.vulkan_functions);
3977 instance.create_info.add_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
3978 instance.CheckCreate();
3979
3980 PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR GetPhysicalDeviceDisplayPlanePropertiesKHR =
3981 instance.load("vkGetPhysicalDeviceDisplayPlanePropertiesKHR");
3982 ASSERT_NE(GetPhysicalDeviceDisplayPlanePropertiesKHR, nullptr);
3983
3984 uint32_t driver_count = 1;
3985 VkPhysicalDevice physical_device;
3986 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
3987 ASSERT_EQ(driver_count, 1U);
3988
3989 std::vector<VkDisplayPlanePropertiesKHR> props{};
3990 uint32_t prop_count = 0;
3991 ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayPlanePropertiesKHR(physical_device, &prop_count, nullptr));
3992 ASSERT_EQ(env.get_test_icd(0).physical_devices.back().display_plane_properties.size(), prop_count);
3993 props.resize(prop_count);
3994 ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayPlanePropertiesKHR(physical_device, &prop_count, props.data()));
3995 ASSERT_EQ(env.get_test_icd(0).physical_devices.back().display_plane_properties.size(), prop_count);
3996
3997 ASSERT_TRUE(CompareDisplayPlanePropData(props, env.get_test_icd(0).physical_devices.back().display_plane_properties));
3998 }
3999
4000 // Test vkGetPhysicalDeviceDisplayPlanePropertiesKHR where instance supports it with some ICDs that both support
4001 // and don't support it:
4002 // ICD 0 supports
4003 // Physical device 0 does not
4004 // Physical device 1 does
4005 // Physical device 2 does not
4006 // ICD 1 doesn't support
4007 // Physical device 3 does not
4008 // ICD 2 supports
4009 // Physical device 4 does not
4010 // Physical device 5 does not
4011 // ICD 3 supports
4012 // Physical device 6 does
TEST(LoaderInstPhysDevExts, PhysDevDispPlanePropsKHRMixed)4013 TEST(LoaderInstPhysDevExts, PhysDevDispPlanePropsKHRMixed) {
4014 FrameworkEnvironment env{};
4015 const uint32_t max_icd_count = 4;
4016 const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
4017 const uint32_t max_phys_devs = 7;
4018
4019 for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
4020 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, icd != 1 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0));
4021 auto& cur_icd = env.get_test_icd(icd);
4022 cur_icd.icd_api_version = VK_API_VERSION_1_0;
4023
4024 // ICD 1 should not have 1.1
4025 if (icd != 1) {
4026 cur_icd.icd_api_version = VK_API_VERSION_1_1;
4027 cur_icd.add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
4028 }
4029
4030 uint32_t rand_vendor_id;
4031 uint32_t rand_driver_vers;
4032 FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
4033
4034 for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
4035 uint32_t device_version = VK_API_VERSION_1_0;
4036 cur_icd.physical_devices.push_back({});
4037 auto& cur_dev = cur_icd.physical_devices.back();
4038
4039 // 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
4040 if ((icd == 0 && dev == 1) || icd == 3) {
4041 cur_dev.extensions.push_back({VK_KHR_DISPLAY_EXTENSION_NAME, 0});
4042 device_version = VK_API_VERSION_1_1;
4043 }
4044
4045 // Still set physical device properties (so we can determine if device is correct API version)
4046 FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
4047 FillInRandomDisplayPlanePropData(cur_dev.display_plane_properties);
4048 }
4049 }
4050
4051 InstWrapper instance(env.vulkan_functions);
4052 instance.create_info.add_extension(VK_KHR_DISPLAY_EXTENSION_NAME);
4053 instance.CheckCreate();
4054
4055 PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR GetPhysicalDeviceDisplayPlanePropertiesKHR =
4056 instance.load("vkGetPhysicalDeviceDisplayPlanePropertiesKHR");
4057 ASSERT_NE(GetPhysicalDeviceDisplayPlanePropertiesKHR, nullptr);
4058
4059 uint32_t device_count = max_phys_devs;
4060 std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
4061 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
4062 ASSERT_EQ(device_count, max_phys_devs);
4063
4064 for (uint32_t dev = 0; dev < device_count; ++dev) {
4065 VkPhysicalDeviceProperties pd_props{};
4066 instance->vkGetPhysicalDeviceProperties(physical_devices[dev], &pd_props);
4067
4068 for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
4069 auto& cur_icd = env.get_test_icd(icd);
4070 bool found = false;
4071 for (uint32_t pd = 0; pd < dev_counts[icd]; ++pd) {
4072 auto& cur_dev = cur_icd.physical_devices[pd];
4073 // Find the ICD device matching the physical device we're looking at info for so we can compare the
4074 // physical devices info with the returned info.
4075 if (cur_dev.properties.apiVersion == pd_props.apiVersion && cur_dev.properties.deviceID == pd_props.deviceID &&
4076 cur_dev.properties.deviceType == pd_props.deviceType &&
4077 cur_dev.properties.driverVersion == pd_props.driverVersion &&
4078 cur_dev.properties.vendorID == pd_props.vendorID) {
4079 std::vector<VkDisplayPlanePropertiesKHR> props{};
4080 uint32_t prop_count = 0;
4081 ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayPlanePropertiesKHR(physical_devices[dev], &prop_count, nullptr));
4082 if (icd == 1) {
4083 // For this extension, if no support exists (like for ICD 1), the value of 0 should be returned by the
4084 // loader.
4085 ASSERT_EQ(0U, prop_count);
4086 } else {
4087 ASSERT_EQ(cur_dev.display_plane_properties.size(), prop_count);
4088 props.resize(prop_count);
4089 ASSERT_EQ(VK_SUCCESS,
4090 GetPhysicalDeviceDisplayPlanePropertiesKHR(physical_devices[dev], &prop_count, props.data()));
4091 ASSERT_EQ(cur_dev.display_plane_properties.size(), prop_count);
4092
4093 ASSERT_TRUE(CompareDisplayPlanePropData(props, cur_dev.display_plane_properties));
4094 }
4095 found = true;
4096 break;
4097 }
4098 }
4099 if (found) {
4100 break;
4101 }
4102 }
4103 }
4104 }
4105
4106 // Test vkGetDisplayPlaneSupportedDisplaysKHR where nothing supports it.
TEST(LoaderInstPhysDevExts, GetDispPlaneSupDispsKHRNoSupport)4107 TEST(LoaderInstPhysDevExts, GetDispPlaneSupDispsKHRNoSupport) {
4108 FrameworkEnvironment env{};
4109 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
4110 env.get_test_icd(0).physical_devices.push_back({});
4111
4112 InstWrapper instance(env.vulkan_functions);
4113 instance.CheckCreate();
4114
4115 PFN_vkGetDisplayPlaneSupportedDisplaysKHR GetDisplayPlaneSupportedDisplaysKHR =
4116 instance.load("vkGetDisplayPlaneSupportedDisplaysKHR");
4117 ASSERT_EQ(GetDisplayPlaneSupportedDisplaysKHR, nullptr);
4118 }
4119
4120 // Test vkGetDisplayPlaneSupportedDisplaysKHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, GetDispPlaneSupDispsKHRNoICDSupport)4121 TEST(LoaderInstPhysDevExts, GetDispPlaneSupDispsKHRNoICDSupport) {
4122 FrameworkEnvironment env{};
4123 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
4124 env.get_test_icd(0).physical_devices.push_back({});
4125
4126 InstWrapper instance(env.vulkan_functions);
4127 instance.create_info.add_extension(VK_KHR_DISPLAY_EXTENSION_NAME);
4128 instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
4129
4130 PFN_vkGetDisplayPlaneSupportedDisplaysKHR GetDisplayPlaneSupportedDisplaysKHR =
4131 instance.load("vkGetDisplayPlaneSupportedDisplaysKHR");
4132 ASSERT_EQ(GetDisplayPlaneSupportedDisplaysKHR, nullptr);
4133 }
4134
4135 // Fill in random but valid data into the display plane property data struct for the current physical device
GenerateRandomDisplays(std::vector<VkDisplayKHR>& disps)4136 void GenerateRandomDisplays(std::vector<VkDisplayKHR>& disps) {
4137 disps.resize((rand() % 5) + 1);
4138 for (uint32_t i = 0; i < disps.size(); ++i) {
4139 disps[i] = CreateRandomDisplay();
4140 }
4141 }
4142
4143 // Compare the display plane property data structs
CompareDisplays(const std::vector<VkDisplayKHR>& disps1, const std::vector<VkDisplayKHR>& disps2)4144 bool CompareDisplays(const std::vector<VkDisplayKHR>& disps1, const std::vector<VkDisplayKHR>& disps2) {
4145 if (disps1.size() != disps2.size()) return false;
4146 bool equal = true;
4147 for (uint32_t i = 0; i < disps1.size(); ++i) {
4148 equal = equal && disps1[i] == disps2[i];
4149 }
4150 return equal;
4151 }
4152
4153 // Test vGetDisplayPlaneSupportedDisplaysKHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, GetDispPlaneSupDispsKHRInstanceAndICDSupport)4154 TEST(LoaderInstPhysDevExts, GetDispPlaneSupDispsKHRInstanceAndICDSupport) {
4155 FrameworkEnvironment env{};
4156 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
4157 env.get_test_icd(0).add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
4158 env.get_test_icd(0).physical_devices.push_back({});
4159 GenerateRandomDisplays(env.get_test_icd(0).physical_devices.back().displays);
4160
4161 InstWrapper instance(env.vulkan_functions);
4162 instance.create_info.add_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
4163 instance.CheckCreate();
4164
4165 PFN_vkGetDisplayPlaneSupportedDisplaysKHR GetDisplayPlaneSupportedDisplaysKHR =
4166 instance.load("vkGetDisplayPlaneSupportedDisplaysKHR");
4167 ASSERT_NE(GetDisplayPlaneSupportedDisplaysKHR, nullptr);
4168
4169 uint32_t driver_count = 1;
4170 VkPhysicalDevice physical_device;
4171 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
4172 ASSERT_EQ(driver_count, 1U);
4173
4174 std::vector<VkDisplayKHR> disps{};
4175 uint32_t disp_count = 0;
4176 ASSERT_EQ(VK_SUCCESS, GetDisplayPlaneSupportedDisplaysKHR(physical_device, 0, &disp_count, nullptr));
4177 ASSERT_EQ(env.get_test_icd(0).physical_devices.back().displays.size(), disp_count);
4178 disps.resize(disp_count);
4179 ASSERT_EQ(VK_SUCCESS, GetDisplayPlaneSupportedDisplaysKHR(physical_device, 0, &disp_count, disps.data()));
4180 ASSERT_EQ(env.get_test_icd(0).physical_devices.back().displays.size(), disp_count);
4181
4182 ASSERT_TRUE(CompareDisplays(disps, env.get_test_icd(0).physical_devices.back().displays));
4183 }
4184
4185 // Test vkGetDisplayPlaneSupportedDisplaysKHR where instance supports it with some ICDs that both support
4186 // and don't support it:
4187 // ICD 0 supports
4188 // Physical device 0 does not
4189 // Physical device 1 does
4190 // Physical device 2 does not
4191 // ICD 1 doesn't support
4192 // Physical device 3 does not
4193 // ICD 2 supports
4194 // Physical device 4 does not
4195 // Physical device 5 does not
4196 // ICD 3 supports
4197 // Physical device 6 does
TEST(LoaderInstPhysDevExts, GetDispPlaneSupDispsKHRMixed)4198 TEST(LoaderInstPhysDevExts, GetDispPlaneSupDispsKHRMixed) {
4199 FrameworkEnvironment env{};
4200 const uint32_t max_icd_count = 4;
4201 const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
4202 const uint32_t max_phys_devs = 7;
4203
4204 for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
4205 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, icd != 1 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0));
4206 auto& cur_icd = env.get_test_icd(icd);
4207 cur_icd.icd_api_version = VK_API_VERSION_1_0;
4208
4209 // ICD 1 should not have 1.1
4210 if (icd != 1) {
4211 cur_icd.icd_api_version = VK_API_VERSION_1_1;
4212 cur_icd.add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
4213 }
4214
4215 uint32_t rand_vendor_id;
4216 uint32_t rand_driver_vers;
4217 FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
4218
4219 for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
4220 uint32_t device_version = VK_API_VERSION_1_0;
4221 cur_icd.physical_devices.push_back({});
4222 auto& cur_dev = cur_icd.physical_devices.back();
4223
4224 // 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
4225 if ((icd == 0 && dev == 1) || icd == 3) {
4226 cur_dev.extensions.push_back({VK_KHR_DISPLAY_EXTENSION_NAME, 0});
4227 device_version = VK_API_VERSION_1_1;
4228 }
4229
4230 // Still set physical device properties (so we can determine if device is correct API version)
4231 FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
4232 GenerateRandomDisplays(cur_dev.displays);
4233 }
4234 }
4235
4236 InstWrapper instance(env.vulkan_functions);
4237 instance.create_info.add_extension(VK_KHR_DISPLAY_EXTENSION_NAME);
4238 instance.CheckCreate();
4239
4240 PFN_vkGetDisplayPlaneSupportedDisplaysKHR GetDisplayPlaneSupportedDisplaysKHR =
4241 instance.load("vkGetDisplayPlaneSupportedDisplaysKHR");
4242 ASSERT_NE(GetDisplayPlaneSupportedDisplaysKHR, nullptr);
4243
4244 uint32_t device_count = max_phys_devs;
4245 std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
4246 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
4247 ASSERT_EQ(device_count, max_phys_devs);
4248
4249 for (uint32_t dev = 0; dev < device_count; ++dev) {
4250 VkPhysicalDeviceProperties pd_props{};
4251 instance->vkGetPhysicalDeviceProperties(physical_devices[dev], &pd_props);
4252
4253 for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
4254 auto& cur_icd = env.get_test_icd(icd);
4255 bool found = false;
4256 for (uint32_t pd = 0; pd < dev_counts[icd]; ++pd) {
4257 auto& cur_dev = cur_icd.physical_devices[pd];
4258 // Find the ICD device matching the physical device we're looking at info for so we can compare the
4259 // physical devices info with the returned info.
4260 if (cur_dev.properties.apiVersion == pd_props.apiVersion && cur_dev.properties.deviceID == pd_props.deviceID &&
4261 cur_dev.properties.deviceType == pd_props.deviceType &&
4262 cur_dev.properties.driverVersion == pd_props.driverVersion &&
4263 cur_dev.properties.vendorID == pd_props.vendorID) {
4264 std::vector<VkDisplayKHR> disps{};
4265 uint32_t disp_count = 0;
4266 ASSERT_EQ(VK_SUCCESS, GetDisplayPlaneSupportedDisplaysKHR(physical_devices[dev], 0, &disp_count, nullptr));
4267 if (icd == 1) {
4268 // For this extension, if no support exists (like for ICD 1), the value of 0 should be returned by the
4269 // loader.
4270 ASSERT_EQ(0U, disp_count);
4271 } else {
4272 ASSERT_EQ(cur_dev.displays.size(), disp_count);
4273 disps.resize(disp_count);
4274 ASSERT_EQ(VK_SUCCESS,
4275 GetDisplayPlaneSupportedDisplaysKHR(physical_devices[dev], 0, &disp_count, disps.data()));
4276 ASSERT_EQ(cur_dev.displays.size(), disp_count);
4277
4278 ASSERT_TRUE(CompareDisplays(disps, cur_dev.displays));
4279 }
4280 found = true;
4281 break;
4282 }
4283 }
4284 if (found) {
4285 break;
4286 }
4287 }
4288 }
4289 }
4290
4291 // Test vkGetDisplayModePropertiesKHR where nothing supports it.
TEST(LoaderInstPhysDevExts, GetDispModePropsKHRNoSupport)4292 TEST(LoaderInstPhysDevExts, GetDispModePropsKHRNoSupport) {
4293 FrameworkEnvironment env{};
4294 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
4295 env.get_test_icd(0).physical_devices.push_back({});
4296
4297 InstWrapper instance(env.vulkan_functions);
4298 instance.CheckCreate();
4299
4300 PFN_vkGetDisplayModePropertiesKHR GetDisplayModePropertiesKHR = instance.load("vkGetDisplayModePropertiesKHR");
4301 ASSERT_EQ(GetDisplayModePropertiesKHR, nullptr);
4302 }
4303
4304 // Test vkGetDisplayModePropertiesKHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, GetDispModePropsKHRNoICDSupport)4305 TEST(LoaderInstPhysDevExts, GetDispModePropsKHRNoICDSupport) {
4306 FrameworkEnvironment env{};
4307 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
4308 env.get_test_icd(0).physical_devices.push_back({});
4309
4310 InstWrapper instance(env.vulkan_functions);
4311 instance.create_info.add_extension(VK_KHR_DISPLAY_EXTENSION_NAME);
4312 instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
4313
4314 PFN_vkGetDisplayModePropertiesKHR GetDisplayModePropertiesKHR = instance.load("vkGetDisplayModePropertiesKHR");
4315 ASSERT_EQ(GetDisplayModePropertiesKHR, nullptr);
4316 }
4317
4318 // Fill in random but valid data into the display mode properties data struct for the current physical device
GenerateRandomDisplayModeProps(std::vector<VkDisplayModePropertiesKHR>& disps)4319 void GenerateRandomDisplayModeProps(std::vector<VkDisplayModePropertiesKHR>& disps) {
4320 disps.resize((rand() % 5) + 1);
4321 for (uint32_t i = 0; i < disps.size(); ++i) {
4322 disps[i].displayMode = CreateRandomDisplayMode();
4323 disps[i].parameters.visibleRegion.width = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
4324 disps[i].parameters.visibleRegion.height = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
4325 disps[i].parameters.refreshRate = 1 << (rand() % 8);
4326 }
4327 }
4328
4329 // Compare the display mode properties data structs
CompareDisplayModeProps(const std::vector<VkDisplayModePropertiesKHR>& disps1, const std::vector<VkDisplayModePropertiesKHR>& disps2)4330 bool CompareDisplayModeProps(const std::vector<VkDisplayModePropertiesKHR>& disps1,
4331 const std::vector<VkDisplayModePropertiesKHR>& disps2) {
4332 if (disps1.size() != disps2.size()) return false;
4333 bool equal = true;
4334 for (uint32_t i = 0; i < disps1.size(); ++i) {
4335 equal = equal && disps1[i].displayMode == disps2[i].displayMode;
4336 equal = equal && disps1[i].parameters.visibleRegion.width == disps2[i].parameters.visibleRegion.width;
4337 equal = equal && disps1[i].parameters.visibleRegion.height == disps2[i].parameters.visibleRegion.height;
4338 equal = equal && disps1[i].parameters.refreshRate == disps2[i].parameters.refreshRate;
4339 }
4340 return equal;
4341 }
4342
4343 // Test vGetDisplayModePropertiesKHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, GetDispModePropsKHRInstanceAndICDSupport)4344 TEST(LoaderInstPhysDevExts, GetDispModePropsKHRInstanceAndICDSupport) {
4345 FrameworkEnvironment env{};
4346 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
4347 env.get_test_icd(0).add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
4348 env.get_test_icd(0).physical_devices.push_back({});
4349 GenerateRandomDisplayModeProps(env.get_test_icd(0).physical_devices.back().display_mode_properties);
4350
4351 InstWrapper instance(env.vulkan_functions);
4352 instance.create_info.add_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
4353 instance.CheckCreate();
4354
4355 PFN_vkGetDisplayModePropertiesKHR GetDisplayModePropertiesKHR = instance.load("vkGetDisplayModePropertiesKHR");
4356 ASSERT_NE(GetDisplayModePropertiesKHR, nullptr);
4357
4358 uint32_t driver_count = 1;
4359 VkPhysicalDevice physical_device;
4360 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
4361 ASSERT_EQ(driver_count, 1U);
4362
4363 std::vector<VkDisplayModePropertiesKHR> props{};
4364 uint32_t props_count = 0;
4365 ASSERT_EQ(VK_SUCCESS, GetDisplayModePropertiesKHR(physical_device, VK_NULL_HANDLE, &props_count, nullptr));
4366 ASSERT_EQ(env.get_test_icd(0).physical_devices.back().display_mode_properties.size(), props_count);
4367 props.resize(props_count);
4368 ASSERT_EQ(VK_SUCCESS, GetDisplayModePropertiesKHR(physical_device, VK_NULL_HANDLE, &props_count, props.data()));
4369 ASSERT_EQ(env.get_test_icd(0).physical_devices.back().display_mode_properties.size(), props_count);
4370
4371 ASSERT_TRUE(CompareDisplayModeProps(props, env.get_test_icd(0).physical_devices.back().display_mode_properties));
4372 }
4373
4374 // Test vkGetDisplayModePropertiesKHR where instance supports it with some ICDs that both support
4375 // and don't support it:
4376 // ICD 0 supports
4377 // Physical device 0 does not
4378 // Physical device 1 does
4379 // Physical device 2 does not
4380 // ICD 1 doesn't support
4381 // Physical device 3 does not
4382 // ICD 2 supports
4383 // Physical device 4 does not
4384 // Physical device 5 does not
4385 // ICD 3 supports
4386 // Physical device 6 does
TEST(LoaderInstPhysDevExts, GetDispModePropsKHRMixed)4387 TEST(LoaderInstPhysDevExts, GetDispModePropsKHRMixed) {
4388 FrameworkEnvironment env{};
4389 const uint32_t max_icd_count = 4;
4390 const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
4391 const uint32_t max_phys_devs = 7;
4392
4393 for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
4394 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, icd != 1 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0));
4395 auto& cur_icd = env.get_test_icd(icd);
4396 cur_icd.icd_api_version = VK_API_VERSION_1_0;
4397
4398 // ICD 1 should not have 1.1
4399 if (icd != 1) {
4400 cur_icd.icd_api_version = VK_API_VERSION_1_1;
4401 cur_icd.add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
4402 }
4403
4404 uint32_t rand_vendor_id;
4405 uint32_t rand_driver_vers;
4406 FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
4407
4408 for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
4409 uint32_t device_version = VK_API_VERSION_1_0;
4410 cur_icd.physical_devices.push_back({});
4411 auto& cur_dev = cur_icd.physical_devices.back();
4412
4413 // 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
4414 if ((icd == 0 && dev == 1) || icd == 3) {
4415 cur_dev.extensions.push_back({VK_KHR_DISPLAY_EXTENSION_NAME, 0});
4416 device_version = VK_API_VERSION_1_1;
4417 }
4418
4419 // Still set physical device properties (so we can determine if device is correct API version)
4420 FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
4421 GenerateRandomDisplayModeProps(cur_dev.display_mode_properties);
4422 }
4423 }
4424
4425 InstWrapper instance(env.vulkan_functions);
4426 instance.create_info.add_extension(VK_KHR_DISPLAY_EXTENSION_NAME);
4427 instance.CheckCreate();
4428
4429 PFN_vkGetDisplayModePropertiesKHR GetDisplayModePropertiesKHR = instance.load("vkGetDisplayModePropertiesKHR");
4430 ASSERT_NE(GetDisplayModePropertiesKHR, nullptr);
4431
4432 uint32_t device_count = max_phys_devs;
4433 std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
4434 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
4435 ASSERT_EQ(device_count, max_phys_devs);
4436
4437 for (uint32_t dev = 0; dev < device_count; ++dev) {
4438 VkPhysicalDeviceProperties pd_props{};
4439 instance->vkGetPhysicalDeviceProperties(physical_devices[dev], &pd_props);
4440
4441 for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
4442 auto& cur_icd = env.get_test_icd(icd);
4443 bool found = false;
4444 for (uint32_t pd = 0; pd < dev_counts[icd]; ++pd) {
4445 auto& cur_dev = cur_icd.physical_devices[pd];
4446 // Find the ICD device matching the physical device we're looking at info for so we can compare the
4447 // physical devices info with the returned info.
4448 if (cur_dev.properties.apiVersion == pd_props.apiVersion && cur_dev.properties.deviceID == pd_props.deviceID &&
4449 cur_dev.properties.deviceType == pd_props.deviceType &&
4450 cur_dev.properties.driverVersion == pd_props.driverVersion &&
4451 cur_dev.properties.vendorID == pd_props.vendorID) {
4452 uint32_t props_count = 0;
4453 ASSERT_EQ(VK_SUCCESS,
4454 GetDisplayModePropertiesKHR(physical_devices[dev], VK_NULL_HANDLE, &props_count, nullptr));
4455 if (icd == 1) {
4456 // For this extension, if no support exists (like for ICD 1), the value of 0 should be returned by the
4457 // loader.
4458 ASSERT_EQ(0U, props_count);
4459 } else {
4460 std::vector<VkDisplayModePropertiesKHR> props{};
4461 ASSERT_EQ(cur_dev.display_mode_properties.size(), props_count);
4462 props.resize(props_count);
4463 ASSERT_EQ(VK_SUCCESS,
4464 GetDisplayModePropertiesKHR(physical_devices[dev], VK_NULL_HANDLE, &props_count, props.data()));
4465 ASSERT_EQ(cur_dev.display_mode_properties.size(), props_count);
4466
4467 ASSERT_TRUE(CompareDisplayModeProps(props, cur_dev.display_mode_properties));
4468 }
4469 found = true;
4470 break;
4471 }
4472 }
4473 if (found) {
4474 break;
4475 }
4476 }
4477 }
4478 }
4479
4480 // Test vkCreateDisplayModeKHR where nothing supports it.
TEST(LoaderInstPhysDevExts, GetDispModesKHRNoSupport)4481 TEST(LoaderInstPhysDevExts, GetDispModesKHRNoSupport) {
4482 FrameworkEnvironment env{};
4483 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
4484 env.get_test_icd(0).physical_devices.push_back({});
4485
4486 InstWrapper instance(env.vulkan_functions);
4487 instance.CheckCreate();
4488
4489 PFN_vkCreateDisplayModeKHR CreateDisplayModeKHR = instance.load("vkCreateDisplayModeKHR");
4490 ASSERT_EQ(CreateDisplayModeKHR, nullptr);
4491 }
4492
4493 // Test vkCreateDisplayModeKHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, GetDispModesKHRNoICDSupport)4494 TEST(LoaderInstPhysDevExts, GetDispModesKHRNoICDSupport) {
4495 FrameworkEnvironment env{};
4496 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
4497 env.get_test_icd(0).physical_devices.push_back({});
4498
4499 InstWrapper instance(env.vulkan_functions);
4500 instance.create_info.add_extension(VK_KHR_DISPLAY_EXTENSION_NAME);
4501 instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
4502
4503 PFN_vkCreateDisplayModeKHR CreateDisplayModeKHR = instance.load("vkCreateDisplayModeKHR");
4504 ASSERT_EQ(CreateDisplayModeKHR, nullptr);
4505 }
4506
4507 // Compare the display modes
CompareDisplayModes(const VkDisplayModeKHR& disps1, VkDisplayModeKHR& disps2)4508 bool CompareDisplayModes(const VkDisplayModeKHR& disps1, VkDisplayModeKHR& disps2) { return disps1 == disps2; }
4509
4510 // Test vkCreateDisplayModeKHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, GetDispModesKHRInstanceAndICDSupport)4511 TEST(LoaderInstPhysDevExts, GetDispModesKHRInstanceAndICDSupport) {
4512 FrameworkEnvironment env{};
4513 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
4514 env.get_test_icd(0).add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
4515 env.get_test_icd(0).physical_devices.push_back({});
4516 env.get_test_icd(0).physical_devices.back().display_mode = CreateRandomDisplayMode();
4517
4518 InstWrapper instance(env.vulkan_functions);
4519 instance.create_info.add_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
4520 instance.CheckCreate();
4521
4522 PFN_vkCreateDisplayModeKHR CreateDisplayModeKHR = instance.load("vkCreateDisplayModeKHR");
4523 ASSERT_NE(CreateDisplayModeKHR, nullptr);
4524
4525 uint32_t driver_count = 1;
4526 VkPhysicalDevice physical_device;
4527 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
4528 ASSERT_EQ(driver_count, 1U);
4529
4530 VkDisplayModeKHR mode{};
4531 VkDisplayModeCreateInfoKHR create_info{VK_STRUCTURE_TYPE_DISPLAY_MODE_CREATE_INFO_KHR};
4532 ASSERT_EQ(VK_SUCCESS, CreateDisplayModeKHR(physical_device, VK_NULL_HANDLE, &create_info, nullptr, &mode));
4533 ASSERT_TRUE(CompareDisplayModes(mode, env.get_test_icd(0).physical_devices.back().display_mode));
4534 }
4535
4536 // Test vkCreateDisplayModeKHR where instance supports it with some ICDs that both support
4537 // and don't support it:
4538 // ICD 0 supports
4539 // Physical device 0 does not
4540 // Physical device 1 does
4541 // Physical device 2 does not
4542 // ICD 1 doesn't support
4543 // Physical device 3 does not
4544 // ICD 2 supports
4545 // Physical device 4 does not
4546 // Physical device 5 does not
4547 // ICD 3 supports
4548 // Physical device 6 does
TEST(LoaderInstPhysDevExts, GetDispModesKHRMixed)4549 TEST(LoaderInstPhysDevExts, GetDispModesKHRMixed) {
4550 FrameworkEnvironment env{};
4551 const uint32_t max_icd_count = 4;
4552 const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
4553 const uint32_t max_phys_devs = 7;
4554
4555 for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
4556 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, icd != 1 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0));
4557 auto& cur_icd = env.get_test_icd(icd);
4558 cur_icd.icd_api_version = VK_API_VERSION_1_0;
4559
4560 // ICD 1 should not have 1.1
4561 if (icd != 1) {
4562 cur_icd.icd_api_version = VK_API_VERSION_1_1;
4563 cur_icd.add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
4564 }
4565
4566 uint32_t rand_vendor_id;
4567 uint32_t rand_driver_vers;
4568 FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
4569
4570 for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
4571 uint32_t device_version = VK_API_VERSION_1_0;
4572 cur_icd.physical_devices.push_back({});
4573 auto& cur_dev = cur_icd.physical_devices.back();
4574
4575 // 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
4576 if ((icd == 0 && dev == 1) || icd == 3) {
4577 cur_dev.extensions.push_back({VK_KHR_DISPLAY_EXTENSION_NAME, 0});
4578 device_version = VK_API_VERSION_1_1;
4579 }
4580
4581 // Still set physical device properties (so we can determine if device is correct API version)
4582 FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
4583 cur_dev.display_mode = CreateRandomDisplayMode();
4584 }
4585 }
4586
4587 InstWrapper instance(env.vulkan_functions);
4588 instance.create_info.add_extension(VK_KHR_DISPLAY_EXTENSION_NAME);
4589 instance.CheckCreate();
4590
4591 PFN_vkCreateDisplayModeKHR CreateDisplayModeKHR = instance.load("vkCreateDisplayModeKHR");
4592 ASSERT_NE(CreateDisplayModeKHR, nullptr);
4593
4594 uint32_t device_count = max_phys_devs;
4595 std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
4596 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
4597 ASSERT_EQ(device_count, max_phys_devs);
4598
4599 for (uint32_t dev = 0; dev < device_count; ++dev) {
4600 VkPhysicalDeviceProperties pd_props{};
4601 instance->vkGetPhysicalDeviceProperties(physical_devices[dev], &pd_props);
4602
4603 for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
4604 auto& cur_icd = env.get_test_icd(icd);
4605 bool found = false;
4606 for (uint32_t pd = 0; pd < dev_counts[icd]; ++pd) {
4607 auto& cur_dev = cur_icd.physical_devices[pd];
4608 // Find the ICD device matching the physical device we're looking at info for so we can compare the
4609 // physical devices info with the returned info.
4610 if (cur_dev.properties.apiVersion == pd_props.apiVersion && cur_dev.properties.deviceID == pd_props.deviceID &&
4611 cur_dev.properties.deviceType == pd_props.deviceType &&
4612 cur_dev.properties.driverVersion == pd_props.driverVersion &&
4613 cur_dev.properties.vendorID == pd_props.vendorID) {
4614 VkDisplayModeKHR mode{};
4615 VkDisplayModeCreateInfoKHR create_info{VK_STRUCTURE_TYPE_DISPLAY_MODE_CREATE_INFO_KHR};
4616 if (icd == 1) {
4617 // Unsupported ICD should return initialization failed (instead of crash)
4618 ASSERT_EQ(VK_ERROR_INITIALIZATION_FAILED,
4619 CreateDisplayModeKHR(physical_devices[dev], VK_NULL_HANDLE, &create_info, nullptr, &mode));
4620 } else {
4621 ASSERT_EQ(VK_SUCCESS,
4622 CreateDisplayModeKHR(physical_devices[dev], VK_NULL_HANDLE, &create_info, nullptr, &mode));
4623 ASSERT_TRUE(CompareDisplayModes(mode, cur_dev.display_mode));
4624 }
4625 found = true;
4626 break;
4627 }
4628 }
4629 if (found) {
4630 break;
4631 }
4632 }
4633 }
4634 }
4635
4636 // Test vkGetDisplayPlaneCapabilitiesKHR where nothing supports it.
TEST(LoaderInstPhysDevExts, GetDispPlaneCapsKHRNoSupport)4637 TEST(LoaderInstPhysDevExts, GetDispPlaneCapsKHRNoSupport) {
4638 FrameworkEnvironment env{};
4639 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
4640 env.get_test_icd(0).physical_devices.push_back({});
4641
4642 InstWrapper instance(env.vulkan_functions);
4643 instance.CheckCreate();
4644
4645 PFN_vkGetDisplayPlaneCapabilitiesKHR GetDisplayPlaneCapabilitiesKHR = instance.load("vkGetDisplayPlaneCapabilitiesKHR");
4646 ASSERT_EQ(GetDisplayPlaneCapabilitiesKHR, nullptr);
4647 }
4648
4649 // Test vkGetDisplayPlaneCapabilitiesKHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, GetDispPlaneCapsKHRNoICDSupport)4650 TEST(LoaderInstPhysDevExts, GetDispPlaneCapsKHRNoICDSupport) {
4651 FrameworkEnvironment env{};
4652 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
4653 env.get_test_icd(0).physical_devices.push_back({});
4654
4655 InstWrapper instance(env.vulkan_functions);
4656 instance.create_info.add_extension(VK_KHR_DISPLAY_EXTENSION_NAME);
4657 instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
4658
4659 PFN_vkGetDisplayPlaneCapabilitiesKHR GetDisplayPlaneCapabilitiesKHR = instance.load("vkGetDisplayPlaneCapabilitiesKHR");
4660 ASSERT_EQ(GetDisplayPlaneCapabilitiesKHR, nullptr);
4661 }
4662
4663 // Fill in random but valid data into the display plane caps for the current physical device
GenerateRandomDisplayPlaneCaps(VkDisplayPlaneCapabilitiesKHR& caps)4664 void GenerateRandomDisplayPlaneCaps(VkDisplayPlaneCapabilitiesKHR& caps) {
4665 caps.supportedAlpha = static_cast<VkDisplayPlaneAlphaFlagsKHR>((rand() % 0xFFFFFFF) + 1);
4666 caps.minSrcPosition.x = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
4667 caps.minSrcPosition.y = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
4668 caps.maxSrcPosition.x = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
4669 caps.maxSrcPosition.y = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
4670 caps.minSrcExtent.width = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
4671 caps.minSrcExtent.height = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
4672 caps.maxSrcExtent.width = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
4673 caps.maxSrcExtent.height = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
4674 caps.minDstPosition.x = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
4675 caps.minDstPosition.y = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
4676 caps.maxDstPosition.x = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
4677 caps.maxDstPosition.y = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
4678 caps.minDstExtent.width = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
4679 caps.minDstExtent.height = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
4680 caps.maxDstExtent.width = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
4681 caps.maxDstExtent.height = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
4682 }
4683
4684 // Compare the display plane caps
CompareDisplayPlaneCaps(const VkDisplayPlaneCapabilitiesKHR& caps1, VkDisplayPlaneCapabilitiesKHR& caps2, bool supported = true)4685 bool CompareDisplayPlaneCaps(const VkDisplayPlaneCapabilitiesKHR& caps1, VkDisplayPlaneCapabilitiesKHR& caps2,
4686 bool supported = true) {
4687 bool equal = true;
4688 if (supported) {
4689 equal = equal && caps1.supportedAlpha == caps2.supportedAlpha;
4690 equal = equal && caps1.minSrcPosition.x == caps2.minSrcPosition.x;
4691 equal = equal && caps1.minSrcPosition.y == caps2.minSrcPosition.y;
4692 equal = equal && caps1.maxSrcPosition.x == caps2.maxSrcPosition.x;
4693 equal = equal && caps1.maxSrcPosition.y == caps2.maxSrcPosition.y;
4694 equal = equal && caps1.minSrcExtent.width == caps2.minSrcExtent.width;
4695 equal = equal && caps1.minSrcExtent.height == caps2.minSrcExtent.height;
4696 equal = equal && caps1.maxSrcExtent.width == caps2.maxSrcExtent.width;
4697 equal = equal && caps1.maxSrcExtent.height == caps2.maxSrcExtent.height;
4698 equal = equal && caps1.minDstPosition.x == caps2.minDstPosition.x;
4699 equal = equal && caps1.minDstPosition.y == caps2.minDstPosition.y;
4700 equal = equal && caps1.maxDstPosition.x == caps2.maxDstPosition.x;
4701 equal = equal && caps1.maxDstPosition.y == caps2.maxDstPosition.y;
4702 equal = equal && caps1.minDstExtent.width == caps2.minDstExtent.width;
4703 equal = equal && caps1.minDstExtent.height == caps2.minDstExtent.height;
4704 equal = equal && caps1.maxDstExtent.width == caps2.maxDstExtent.width;
4705 equal = equal && caps1.maxDstExtent.height == caps2.maxDstExtent.height;
4706 } else {
4707 equal = equal && caps1.supportedAlpha == 0;
4708 equal = equal && caps1.minSrcPosition.x == 0;
4709 equal = equal && caps1.minSrcPosition.y == 0;
4710 equal = equal && caps1.maxSrcPosition.x == 0;
4711 equal = equal && caps1.maxSrcPosition.y == 0;
4712 equal = equal && caps1.minSrcExtent.width == 0;
4713 equal = equal && caps1.minSrcExtent.height == 0;
4714 equal = equal && caps1.maxSrcExtent.width == 0;
4715 equal = equal && caps1.maxSrcExtent.height == 0;
4716 equal = equal && caps1.minDstPosition.x == 0;
4717 equal = equal && caps1.minDstPosition.y == 0;
4718 equal = equal && caps1.maxDstPosition.x == 0;
4719 equal = equal && caps1.maxDstPosition.y == 0;
4720 equal = equal && caps1.minDstExtent.width == 0;
4721 equal = equal && caps1.minDstExtent.height == 0;
4722 equal = equal && caps1.maxDstExtent.width == 0;
4723 equal = equal && caps1.maxDstExtent.height == 0;
4724 }
4725 return equal;
4726 }
4727
4728 // Test vkGetDisplayPlaneCapabilitiesKHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, GetDispPlaneCapsKHRInstanceAndICDSupport)4729 TEST(LoaderInstPhysDevExts, GetDispPlaneCapsKHRInstanceAndICDSupport) {
4730 FrameworkEnvironment env{};
4731 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
4732 env.get_test_icd(0).add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
4733 env.get_test_icd(0).physical_devices.push_back({});
4734 GenerateRandomDisplayPlaneCaps(env.get_test_icd(0).physical_devices.back().display_plane_capabilities);
4735
4736 InstWrapper instance(env.vulkan_functions);
4737 instance.create_info.add_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
4738 instance.CheckCreate();
4739
4740 PFN_vkGetDisplayPlaneCapabilitiesKHR GetDisplayPlaneCapabilitiesKHR = instance.load("vkGetDisplayPlaneCapabilitiesKHR");
4741 ASSERT_NE(GetDisplayPlaneCapabilitiesKHR, nullptr);
4742
4743 uint32_t driver_count = 1;
4744 VkPhysicalDevice physical_device;
4745 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
4746 ASSERT_EQ(driver_count, 1U);
4747
4748 VkDisplayPlaneCapabilitiesKHR caps{};
4749 ASSERT_EQ(VK_SUCCESS, GetDisplayPlaneCapabilitiesKHR(physical_device, 0, 0, &caps));
4750 ASSERT_TRUE(CompareDisplayPlaneCaps(caps, env.get_test_icd(0).physical_devices.back().display_plane_capabilities));
4751 }
4752
4753 // Test vkGetDisplayPlaneCapabilitiesKHR where instance supports it with some ICDs that both support
4754 // and don't support it:
4755 // ICD 0 supports
4756 // Physical device 0 does not
4757 // Physical device 1 does
4758 // Physical device 2 does not
4759 // ICD 1 doesn't support
4760 // Physical device 3 does not
4761 // ICD 2 supports
4762 // Physical device 4 does not
4763 // Physical device 5 does not
4764 // ICD 3 supports
4765 // Physical device 6 does
TEST(LoaderInstPhysDevExts, GetDispPlaneCapsKHRMixed)4766 TEST(LoaderInstPhysDevExts, GetDispPlaneCapsKHRMixed) {
4767 FrameworkEnvironment env{};
4768 const uint32_t max_icd_count = 4;
4769 const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
4770 const uint32_t max_phys_devs = 7;
4771
4772 for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
4773 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, icd != 1 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0));
4774 auto& cur_icd = env.get_test_icd(icd);
4775 cur_icd.icd_api_version = VK_API_VERSION_1_0;
4776
4777 // ICD 1 should not have 1.1
4778 if (icd != 1) {
4779 cur_icd.icd_api_version = VK_API_VERSION_1_1;
4780 cur_icd.add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
4781 }
4782
4783 uint32_t rand_vendor_id;
4784 uint32_t rand_driver_vers;
4785 FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
4786
4787 for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
4788 uint32_t device_version = VK_API_VERSION_1_0;
4789 cur_icd.physical_devices.push_back({});
4790 auto& cur_dev = cur_icd.physical_devices.back();
4791
4792 // 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
4793 if ((icd == 0 && dev == 1) || icd == 3) {
4794 cur_dev.extensions.push_back({VK_KHR_DISPLAY_EXTENSION_NAME, 0});
4795 device_version = VK_API_VERSION_1_1;
4796 }
4797
4798 // Still set physical device properties (so we can determine if device is correct API version)
4799 FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
4800 GenerateRandomDisplayPlaneCaps(cur_dev.display_plane_capabilities);
4801 }
4802 }
4803
4804 InstWrapper instance(env.vulkan_functions);
4805 instance.create_info.add_extension(VK_KHR_DISPLAY_EXTENSION_NAME);
4806 instance.CheckCreate();
4807
4808 PFN_vkGetDisplayPlaneCapabilitiesKHR GetDisplayPlaneCapabilitiesKHR = instance.load("vkGetDisplayPlaneCapabilitiesKHR");
4809 ASSERT_NE(GetDisplayPlaneCapabilitiesKHR, nullptr);
4810
4811 uint32_t device_count = max_phys_devs;
4812 std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
4813 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
4814 ASSERT_EQ(device_count, max_phys_devs);
4815
4816 for (uint32_t dev = 0; dev < device_count; ++dev) {
4817 VkPhysicalDeviceProperties pd_props{};
4818 instance->vkGetPhysicalDeviceProperties(physical_devices[dev], &pd_props);
4819
4820 for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
4821 auto& cur_icd = env.get_test_icd(icd);
4822 bool found = false;
4823 for (uint32_t pd = 0; pd < dev_counts[icd]; ++pd) {
4824 auto& cur_dev = cur_icd.physical_devices[pd];
4825 // Find the ICD device matching the physical device we're looking at info for so we can compare the
4826 // physical devices info with the returned info.
4827 if (cur_dev.properties.apiVersion == pd_props.apiVersion && cur_dev.properties.deviceID == pd_props.deviceID &&
4828 cur_dev.properties.deviceType == pd_props.deviceType &&
4829 cur_dev.properties.driverVersion == pd_props.driverVersion &&
4830 cur_dev.properties.vendorID == pd_props.vendorID) {
4831 VkDisplayPlaneCapabilitiesKHR caps{};
4832 ASSERT_EQ(VK_SUCCESS, GetDisplayPlaneCapabilitiesKHR(physical_devices[dev], 0, 0, &caps));
4833 ASSERT_TRUE(CompareDisplayPlaneCaps(caps, cur_dev.display_plane_capabilities, icd != 1));
4834 found = true;
4835 break;
4836 }
4837 }
4838 if (found) {
4839 break;
4840 }
4841 }
4842 }
4843 }
4844
4845 //
4846 // VK_KHR_get_display_properties2
4847 //
4848
4849 // Test vkGetPhysicalDeviceDisplayProperties2KHR where nothing supports it.
TEST(LoaderInstPhysDevExts, PhysDevDispProps2KHRNoSupport)4850 TEST(LoaderInstPhysDevExts, PhysDevDispProps2KHRNoSupport) {
4851 FrameworkEnvironment env{};
4852 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
4853 env.get_test_icd(0).physical_devices.push_back({});
4854
4855 InstWrapper instance(env.vulkan_functions);
4856 instance.CheckCreate();
4857
4858 PFN_vkGetPhysicalDeviceDisplayProperties2KHR GetPhysicalDeviceDisplayProperties2KHR =
4859 instance.load("vkGetPhysicalDeviceDisplayProperties2KHR");
4860 ASSERT_EQ(GetPhysicalDeviceDisplayProperties2KHR, nullptr);
4861 }
4862
4863 // Test vkGetPhysicalDeviceDisplayProperties2KHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevDispProps2KHRNoICDSupport)4864 TEST(LoaderInstPhysDevExts, PhysDevDispProps2KHRNoICDSupport) {
4865 FrameworkEnvironment env{};
4866 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
4867 env.get_test_icd(0).physical_devices.push_back({});
4868
4869 InstWrapper instance(env.vulkan_functions);
4870 instance.create_info.add_extension(VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME);
4871 instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
4872
4873 PFN_vkGetPhysicalDeviceDisplayProperties2KHR GetPhysicalDeviceDisplayProperties2KHR =
4874 instance.load("vkGetPhysicalDeviceDisplayProperties2KHR");
4875 ASSERT_EQ(GetPhysicalDeviceDisplayProperties2KHR, nullptr);
4876 }
4877
4878 // Compare the display property data structs
CompareDisplayPropData(const std::vector<VkDisplayPropertiesKHR>& props1, const std::vector<VkDisplayProperties2KHR>& props2)4879 bool CompareDisplayPropData(const std::vector<VkDisplayPropertiesKHR>& props1, const std::vector<VkDisplayProperties2KHR>& props2) {
4880 if (props1.size() != props2.size()) return false;
4881 bool equal = true;
4882 for (uint32_t i = 0; i < props1.size(); ++i) {
4883 equal = equal && props1[i].display == props2[i].displayProperties.display;
4884 equal = equal && props1[i].physicalDimensions.width == props2[i].displayProperties.physicalDimensions.width;
4885 equal = equal && props1[i].physicalDimensions.height == props2[i].displayProperties.physicalDimensions.height;
4886 equal = equal && props1[i].physicalResolution.width == props2[i].displayProperties.physicalResolution.width;
4887 equal = equal && props1[i].physicalResolution.height == props2[i].displayProperties.physicalResolution.height;
4888 equal = equal && props1[i].supportedTransforms == props2[i].displayProperties.supportedTransforms;
4889 equal = equal && props1[i].planeReorderPossible == props2[i].displayProperties.planeReorderPossible;
4890 equal = equal && props1[i].persistentContent == props2[i].displayProperties.persistentContent;
4891 }
4892 return equal;
4893 }
4894
4895 // Test vGetPhysicalDeviceDisplayProperties2KHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, PhysDevDispProps2KHRInstanceAndICDSupport)4896 TEST(LoaderInstPhysDevExts, PhysDevDispProps2KHRInstanceAndICDSupport) {
4897 FrameworkEnvironment env{};
4898 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
4899 Extension first_ext{VK_KHR_DISPLAY_EXTENSION_NAME};
4900 Extension second_ext{VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME};
4901 env.get_test_icd(0).add_instance_extensions({first_ext, second_ext});
4902 env.get_test_icd(0).physical_devices.push_back({});
4903 FillInRandomDisplayPropData(env.get_test_icd(0).physical_devices.back().display_properties);
4904
4905 InstWrapper instance(env.vulkan_functions);
4906 instance.create_info.add_extensions({VK_KHR_DISPLAY_EXTENSION_NAME, VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME});
4907 instance.CheckCreate();
4908
4909 PFN_vkGetPhysicalDeviceDisplayPropertiesKHR GetPhysicalDeviceDisplayPropertiesKHR =
4910 instance.load("vkGetPhysicalDeviceDisplayPropertiesKHR");
4911 ASSERT_NE(GetPhysicalDeviceDisplayPropertiesKHR, nullptr);
4912 PFN_vkGetPhysicalDeviceDisplayProperties2KHR GetPhysicalDeviceDisplayProperties2KHR =
4913 instance.load("vkGetPhysicalDeviceDisplayProperties2KHR");
4914 ASSERT_NE(GetPhysicalDeviceDisplayProperties2KHR, nullptr);
4915
4916 uint32_t driver_count = 1;
4917 VkPhysicalDevice physical_device;
4918 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
4919 ASSERT_EQ(driver_count, 1U);
4920
4921 std::vector<VkDisplayPropertiesKHR> props{};
4922 uint32_t prop_count = 0;
4923 ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayPropertiesKHR(physical_device, &prop_count, nullptr));
4924 ASSERT_NE(0U, prop_count);
4925 props.resize(prop_count);
4926 ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayPropertiesKHR(physical_device, &prop_count, props.data()));
4927
4928 std::vector<VkDisplayProperties2KHR> props2{};
4929 uint32_t prop_count_2 = 0;
4930 ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayProperties2KHR(physical_device, &prop_count_2, nullptr));
4931 ASSERT_EQ(prop_count, prop_count_2);
4932 props2.resize(prop_count_2, {VK_STRUCTURE_TYPE_DISPLAY_PROPERTIES_2_KHR});
4933 ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayProperties2KHR(physical_device, &prop_count_2, props2.data()));
4934 ASSERT_EQ(prop_count, prop_count_2);
4935
4936 ASSERT_TRUE(CompareDisplayPropData(props, props2));
4937 }
4938
4939 // Test vkGetPhysicalDeviceDisplayProperties2KHR where instance supports it with some ICDs that both support
4940 // and don't support it:
4941 // ICD 0 supports
4942 // Physical device 0 does not
4943 // Physical device 1 does
4944 // Physical device 2 does not
4945 // ICD 1 doesn't support
4946 // Physical device 3 does not
4947 // ICD 2 supports
4948 // Physical device 4 does not
4949 // Physical device 5 does not
4950 // ICD 3 supports
4951 // Physical device 6 does
TEST(LoaderInstPhysDevExts, PhysDevDispProps2KHRMixed)4952 TEST(LoaderInstPhysDevExts, PhysDevDispProps2KHRMixed) {
4953 FrameworkEnvironment env{};
4954 const uint32_t max_icd_count = 4;
4955 const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
4956 const uint32_t max_phys_devs = 7;
4957
4958 for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
4959 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, icd != 1 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0));
4960 auto& cur_icd = env.get_test_icd(icd);
4961 cur_icd.icd_api_version = VK_API_VERSION_1_0;
4962 cur_icd.add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
4963
4964 // ICD 1 should not have 1.1
4965 if (icd != 1) {
4966 cur_icd.icd_api_version = VK_API_VERSION_1_1;
4967 cur_icd.add_instance_extension({VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME});
4968 }
4969
4970 uint32_t rand_vendor_id;
4971 uint32_t rand_driver_vers;
4972 FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
4973
4974 for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
4975 uint32_t device_version = VK_API_VERSION_1_0;
4976 cur_icd.physical_devices.push_back({});
4977 auto& cur_dev = cur_icd.physical_devices.back();
4978 cur_dev.extensions.push_back({VK_KHR_DISPLAY_EXTENSION_NAME, 0});
4979
4980 // 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
4981 if ((icd == 0 && dev == 1) || icd == 3) {
4982 cur_dev.extensions.push_back({VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME, 0});
4983 device_version = VK_API_VERSION_1_1;
4984 }
4985
4986 // Still set physical device properties (so we can determine if device is correct API version)
4987 FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
4988 FillInRandomDisplayPropData(cur_dev.display_properties);
4989 }
4990 }
4991
4992 InstWrapper instance(env.vulkan_functions);
4993 instance.create_info.add_extensions({VK_KHR_DISPLAY_EXTENSION_NAME, VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME});
4994 instance.CheckCreate();
4995
4996 PFN_vkGetPhysicalDeviceDisplayPropertiesKHR GetPhysicalDeviceDisplayPropertiesKHR =
4997 instance.load("vkGetPhysicalDeviceDisplayPropertiesKHR");
4998 ASSERT_NE(GetPhysicalDeviceDisplayPropertiesKHR, nullptr);
4999 PFN_vkGetPhysicalDeviceDisplayProperties2KHR GetPhysicalDeviceDisplayProperties2KHR =
5000 instance.load("vkGetPhysicalDeviceDisplayProperties2KHR");
5001 ASSERT_NE(GetPhysicalDeviceDisplayProperties2KHR, nullptr);
5002
5003 uint32_t device_count = max_phys_devs;
5004 std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
5005 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
5006 ASSERT_EQ(device_count, max_phys_devs);
5007
5008 for (uint32_t dev = 0; dev < device_count; ++dev) {
5009 std::vector<VkDisplayPropertiesKHR> props{};
5010 uint32_t prop_count = 0;
5011 ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayPropertiesKHR(physical_devices[dev], &prop_count, nullptr));
5012 ASSERT_NE(0U, prop_count);
5013 props.resize(prop_count);
5014 ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayPropertiesKHR(physical_devices[dev], &prop_count, props.data()));
5015
5016 std::vector<VkDisplayProperties2KHR> props2{};
5017 uint32_t prop_count_2 = 0;
5018 ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayProperties2KHR(physical_devices[dev], &prop_count_2, nullptr));
5019 ASSERT_EQ(prop_count, prop_count_2);
5020 props2.resize(prop_count_2, {VK_STRUCTURE_TYPE_DISPLAY_PROPERTIES_2_KHR});
5021 ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayProperties2KHR(physical_devices[dev], &prop_count_2, props2.data()));
5022 ASSERT_EQ(prop_count, prop_count_2);
5023
5024 ASSERT_TRUE(CompareDisplayPropData(props, props2));
5025 }
5026 }
5027
5028 // Test vkGetPhysicalDeviceDisplayPlaneProperties2KHR where nothing supports it.
TEST(LoaderInstPhysDevExts, PhysDevDispPlaneProps2KHRNoSupport)5029 TEST(LoaderInstPhysDevExts, PhysDevDispPlaneProps2KHRNoSupport) {
5030 FrameworkEnvironment env{};
5031 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
5032 env.get_test_icd(0).physical_devices.push_back({});
5033
5034 InstWrapper instance(env.vulkan_functions);
5035 instance.CheckCreate();
5036
5037 PFN_vkGetPhysicalDeviceDisplayPlaneProperties2KHR GetPhysicalDeviceDisplayPlaneProperties2KHR =
5038 instance.load("vkGetPhysicalDeviceDisplayPlaneProperties2KHR");
5039 ASSERT_EQ(GetPhysicalDeviceDisplayPlaneProperties2KHR, nullptr);
5040 }
5041
5042 // Test vkGetPhysicalDeviceDisplayPlaneProperties2KHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevDispPlaneProps2KHRNoICDSupport)5043 TEST(LoaderInstPhysDevExts, PhysDevDispPlaneProps2KHRNoICDSupport) {
5044 FrameworkEnvironment env{};
5045 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
5046 env.get_test_icd(0).physical_devices.push_back({});
5047
5048 InstWrapper instance(env.vulkan_functions);
5049 instance.create_info.add_extension(VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME);
5050 instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
5051
5052 PFN_vkGetPhysicalDeviceDisplayPlaneProperties2KHR GetPhysicalDeviceDisplayPlaneProperties2KHR =
5053 instance.load("vkGetPhysicalDeviceDisplayPlaneProperties2KHR");
5054 ASSERT_EQ(GetPhysicalDeviceDisplayPlaneProperties2KHR, nullptr);
5055 }
5056
5057 // Compare the display plane property data structs
CompareDisplayPlanePropData(const std::vector<VkDisplayPlanePropertiesKHR>& props1, const std::vector<VkDisplayPlaneProperties2KHR>& props2)5058 bool CompareDisplayPlanePropData(const std::vector<VkDisplayPlanePropertiesKHR>& props1,
5059 const std::vector<VkDisplayPlaneProperties2KHR>& props2) {
5060 if (props1.size() != props2.size()) return false;
5061 bool equal = true;
5062 for (uint32_t i = 0; i < props1.size(); ++i) {
5063 equal = equal && props1[i].currentDisplay == props2[i].displayPlaneProperties.currentDisplay;
5064 equal = equal && props1[i].currentStackIndex == props2[i].displayPlaneProperties.currentStackIndex;
5065 }
5066 return equal;
5067 }
5068
5069 // Test vGetPhysicalDeviceDisplayPlaneProperties2KHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, PhysDevDispPlaneProps2KHRInstanceAndICDSupport)5070 TEST(LoaderInstPhysDevExts, PhysDevDispPlaneProps2KHRInstanceAndICDSupport) {
5071 FrameworkEnvironment env{};
5072 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
5073 Extension first_ext{VK_KHR_DISPLAY_EXTENSION_NAME};
5074 Extension second_ext{VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME};
5075 env.get_test_icd(0).add_instance_extensions({first_ext, second_ext});
5076 env.get_test_icd(0).physical_devices.push_back({});
5077 FillInRandomDisplayPlanePropData(env.get_test_icd(0).physical_devices.back().display_plane_properties);
5078
5079 InstWrapper instance(env.vulkan_functions);
5080 instance.create_info.add_extensions({VK_KHR_DISPLAY_EXTENSION_NAME, VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME});
5081 instance.CheckCreate();
5082
5083 PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR GetPhysicalDeviceDisplayPlanePropertiesKHR =
5084 instance.load("vkGetPhysicalDeviceDisplayPlanePropertiesKHR");
5085 ASSERT_NE(GetPhysicalDeviceDisplayPlanePropertiesKHR, nullptr);
5086 PFN_vkGetPhysicalDeviceDisplayPlaneProperties2KHR GetPhysicalDeviceDisplayPlaneProperties2KHR =
5087 instance.load("vkGetPhysicalDeviceDisplayPlaneProperties2KHR");
5088 ASSERT_NE(GetPhysicalDeviceDisplayPlaneProperties2KHR, nullptr);
5089
5090 uint32_t driver_count = 1;
5091 VkPhysicalDevice physical_device;
5092 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
5093 ASSERT_EQ(driver_count, 1U);
5094
5095 std::vector<VkDisplayPlanePropertiesKHR> props{};
5096 uint32_t prop_count = 0;
5097 ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayPlanePropertiesKHR(physical_device, &prop_count, nullptr));
5098 ASSERT_NE(0U, prop_count);
5099 props.resize(prop_count);
5100 ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayPlanePropertiesKHR(physical_device, &prop_count, props.data()));
5101
5102 std::vector<VkDisplayPlaneProperties2KHR> props2{};
5103 uint32_t prop_count2 = 0;
5104 ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayPlaneProperties2KHR(physical_device, &prop_count2, nullptr));
5105 ASSERT_EQ(prop_count, prop_count2);
5106 props2.resize(prop_count2, {VK_STRUCTURE_TYPE_DISPLAY_PLANE_PROPERTIES_2_KHR});
5107 ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayPlaneProperties2KHR(physical_device, &prop_count2, props2.data()));
5108
5109 ASSERT_TRUE(CompareDisplayPlanePropData(props, props2));
5110 }
5111
5112 // Test vkGetPhysicalDeviceDisplayPlaneProperties2KHR where instance supports it with some ICDs that both support
5113 // and don't support it:
5114 // ICD 0 supports
5115 // Physical device 0 does not
5116 // Physical device 1 does
5117 // Physical device 2 does not
5118 // ICD 1 doesn't support
5119 // Physical device 3 does not
5120 // ICD 2 supports
5121 // Physical device 4 does not
5122 // Physical device 5 does not
5123 // ICD 3 supports
5124 // Physical device 6 does
TEST(LoaderInstPhysDevExts, PhysDevDispPlaneProps2KHRMixed)5125 TEST(LoaderInstPhysDevExts, PhysDevDispPlaneProps2KHRMixed) {
5126 FrameworkEnvironment env{};
5127 const uint32_t max_icd_count = 4;
5128 const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
5129 const uint32_t max_phys_devs = 7;
5130
5131 for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
5132 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, icd != 1 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0));
5133 auto& cur_icd = env.get_test_icd(icd);
5134 cur_icd.icd_api_version = VK_API_VERSION_1_0;
5135 cur_icd.add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
5136
5137 // ICD 1 should not have 1.1
5138 if (icd != 1) {
5139 cur_icd.icd_api_version = VK_API_VERSION_1_1;
5140 cur_icd.add_instance_extension({VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME});
5141 }
5142
5143 uint32_t rand_vendor_id;
5144 uint32_t rand_driver_vers;
5145 FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
5146
5147 for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
5148 uint32_t device_version = VK_API_VERSION_1_0;
5149 cur_icd.physical_devices.push_back({});
5150 auto& cur_dev = cur_icd.physical_devices.back();
5151 cur_dev.extensions.push_back({VK_KHR_DISPLAY_EXTENSION_NAME, 0});
5152
5153 // 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
5154 if ((icd == 0 && dev == 1) || icd == 3) {
5155 cur_dev.extensions.push_back({VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME, 0});
5156 device_version = VK_API_VERSION_1_1;
5157 }
5158
5159 // Still set physical device properties (so we can determine if device is correct API version)
5160 FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
5161 FillInRandomDisplayPlanePropData(cur_dev.display_plane_properties);
5162 }
5163 }
5164
5165 InstWrapper instance(env.vulkan_functions);
5166 instance.create_info.add_extensions({VK_KHR_DISPLAY_EXTENSION_NAME, VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME});
5167 instance.CheckCreate();
5168
5169 PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR GetPhysicalDeviceDisplayPlanePropertiesKHR =
5170 instance.load("vkGetPhysicalDeviceDisplayPlanePropertiesKHR");
5171 ASSERT_NE(GetPhysicalDeviceDisplayPlanePropertiesKHR, nullptr);
5172 PFN_vkGetPhysicalDeviceDisplayPlaneProperties2KHR GetPhysicalDeviceDisplayPlaneProperties2KHR =
5173 instance.load("vkGetPhysicalDeviceDisplayPlaneProperties2KHR");
5174 ASSERT_NE(GetPhysicalDeviceDisplayPlaneProperties2KHR, nullptr);
5175
5176 uint32_t device_count = max_phys_devs;
5177 std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
5178 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
5179 ASSERT_EQ(device_count, max_phys_devs);
5180
5181 for (uint32_t dev = 0; dev < device_count; ++dev) {
5182 std::vector<VkDisplayPlanePropertiesKHR> props{};
5183 uint32_t prop_count = 0;
5184 ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayPlanePropertiesKHR(physical_devices[dev], &prop_count, nullptr));
5185 ASSERT_NE(0U, prop_count);
5186 props.resize(prop_count);
5187 ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayPlanePropertiesKHR(physical_devices[dev], &prop_count, props.data()));
5188
5189 std::vector<VkDisplayPlaneProperties2KHR> props2{};
5190 uint32_t prop_count2 = 0;
5191 ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayPlaneProperties2KHR(physical_devices[dev], &prop_count2, nullptr));
5192 ASSERT_EQ(prop_count, prop_count2);
5193 props2.resize(prop_count2, {VK_STRUCTURE_TYPE_DISPLAY_PLANE_PROPERTIES_2_KHR});
5194 ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceDisplayPlaneProperties2KHR(physical_devices[dev], &prop_count2, props2.data()));
5195
5196 ASSERT_TRUE(CompareDisplayPlanePropData(props, props2));
5197 }
5198 }
5199
5200 // Test vkGetDisplayModeProperties2KHR where nothing supports it.
TEST(LoaderInstPhysDevExts, GetDispModeProps2KHRNoSupport)5201 TEST(LoaderInstPhysDevExts, GetDispModeProps2KHRNoSupport) {
5202 FrameworkEnvironment env{};
5203 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
5204 env.get_test_icd(0).physical_devices.push_back({});
5205
5206 InstWrapper instance(env.vulkan_functions);
5207 instance.CheckCreate();
5208
5209 PFN_vkGetDisplayModeProperties2KHR GetDisplayModeProperties2KHR = instance.load("vkGetDisplayModeProperties2KHR");
5210 ASSERT_EQ(GetDisplayModeProperties2KHR, nullptr);
5211 }
5212
5213 // Test vkGetDisplayModeProperties2KHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, GetDispModeProps2KHRNoICDSupport)5214 TEST(LoaderInstPhysDevExts, GetDispModeProps2KHRNoICDSupport) {
5215 FrameworkEnvironment env{};
5216 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
5217 env.get_test_icd(0).physical_devices.push_back({});
5218
5219 InstWrapper instance(env.vulkan_functions);
5220 instance.create_info.add_extension(VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME);
5221 instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
5222
5223 PFN_vkGetDisplayModeProperties2KHR GetDisplayModeProperties2KHR = instance.load("vkGetDisplayModeProperties2KHR");
5224 ASSERT_EQ(GetDisplayModeProperties2KHR, nullptr);
5225 }
5226
5227 // Compare the display mode properties data structs
CompareDisplayModeProps(const std::vector<VkDisplayModePropertiesKHR>& disps1, const std::vector<VkDisplayModeProperties2KHR>& disps2)5228 bool CompareDisplayModeProps(const std::vector<VkDisplayModePropertiesKHR>& disps1,
5229 const std::vector<VkDisplayModeProperties2KHR>& disps2) {
5230 if (disps1.size() != disps2.size()) return false;
5231
5232 bool equal = true;
5233 for (uint32_t i = 0; i < disps1.size(); ++i) {
5234 equal = equal && disps1[i].displayMode == disps2[i].displayModeProperties.displayMode;
5235 equal = equal && disps1[i].parameters.visibleRegion.width == disps2[i].displayModeProperties.parameters.visibleRegion.width;
5236 equal =
5237 equal && disps1[i].parameters.visibleRegion.height == disps2[i].displayModeProperties.parameters.visibleRegion.height;
5238 equal = equal && disps1[i].parameters.refreshRate == disps2[i].displayModeProperties.parameters.refreshRate;
5239 }
5240 return equal;
5241 }
5242
5243 // Test vGetDisplayModeProperties2KHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, GetDispModeProps2KHRInstanceAndICDSupport)5244 TEST(LoaderInstPhysDevExts, GetDispModeProps2KHRInstanceAndICDSupport) {
5245 FrameworkEnvironment env{};
5246 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
5247 Extension first_ext{VK_KHR_DISPLAY_EXTENSION_NAME};
5248 Extension second_ext{VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME};
5249 env.get_test_icd(0).add_instance_extensions({first_ext, second_ext});
5250 env.get_test_icd(0).physical_devices.push_back({});
5251 GenerateRandomDisplayModeProps(env.get_test_icd(0).physical_devices.back().display_mode_properties);
5252
5253 InstWrapper instance(env.vulkan_functions);
5254 instance.create_info.add_extensions({VK_KHR_DISPLAY_EXTENSION_NAME, VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME});
5255 instance.CheckCreate();
5256
5257 PFN_vkGetDisplayModePropertiesKHR GetDisplayModePropertiesKHR = instance.load("vkGetDisplayModePropertiesKHR");
5258 ASSERT_NE(GetDisplayModePropertiesKHR, nullptr);
5259 PFN_vkGetDisplayModeProperties2KHR GetDisplayModeProperties2KHR = instance.load("vkGetDisplayModeProperties2KHR");
5260 ASSERT_NE(GetDisplayModeProperties2KHR, nullptr);
5261
5262 uint32_t driver_count = 1;
5263 VkPhysicalDevice physical_device;
5264 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
5265 ASSERT_EQ(driver_count, 1U);
5266
5267 std::vector<VkDisplayModePropertiesKHR> props{};
5268 uint32_t props_count1 = 0;
5269 ASSERT_EQ(VK_SUCCESS, GetDisplayModePropertiesKHR(physical_device, VK_NULL_HANDLE, &props_count1, nullptr));
5270 ASSERT_NE(0U, props_count1);
5271 props.resize(props_count1);
5272 ASSERT_EQ(VK_SUCCESS, GetDisplayModePropertiesKHR(physical_device, VK_NULL_HANDLE, &props_count1, props.data()));
5273
5274 std::vector<VkDisplayModeProperties2KHR> props2{};
5275 uint32_t props_count2 = 0;
5276 ASSERT_EQ(VK_SUCCESS, GetDisplayModeProperties2KHR(physical_device, VK_NULL_HANDLE, &props_count2, nullptr));
5277 ASSERT_EQ(props_count1, props_count2);
5278 props2.resize(props_count2, {VK_STRUCTURE_TYPE_DISPLAY_MODE_PROPERTIES_2_KHR});
5279 ASSERT_EQ(VK_SUCCESS, GetDisplayModeProperties2KHR(physical_device, VK_NULL_HANDLE, &props_count2, props2.data()));
5280
5281 ASSERT_TRUE(CompareDisplayModeProps(props, props2));
5282 }
5283
5284 // Test vkGetDisplayModeProperties2KHR where instance supports it with some ICDs that both support
5285 // and don't support it:
5286 // ICD 0 supports
5287 // Physical device 0 does not
5288 // Physical device 1 does
5289 // Physical device 2 does not
5290 // ICD 1 doesn't support
5291 // Physical device 3 does not
5292 // ICD 2 supports
5293 // Physical device 4 does not
5294 // Physical device 5 does not
5295 // ICD 3 supports
5296 // Physical device 6 does
TEST(LoaderInstPhysDevExts, GetDispModeProps2KHRMixed)5297 TEST(LoaderInstPhysDevExts, GetDispModeProps2KHRMixed) {
5298 FrameworkEnvironment env{};
5299 const uint32_t max_icd_count = 4;
5300 const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
5301 const uint32_t max_phys_devs = 7;
5302
5303 for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
5304 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, icd != 1 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0));
5305 auto& cur_icd = env.get_test_icd(icd);
5306 cur_icd.icd_api_version = VK_API_VERSION_1_0;
5307 cur_icd.add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
5308
5309 // ICD 1 should not have 1.1
5310 if (icd != 1) {
5311 cur_icd.icd_api_version = VK_API_VERSION_1_1;
5312 cur_icd.add_instance_extension({VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME});
5313 }
5314
5315 uint32_t rand_vendor_id;
5316 uint32_t rand_driver_vers;
5317 FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
5318
5319 for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
5320 uint32_t device_version = VK_API_VERSION_1_0;
5321 cur_icd.physical_devices.push_back({});
5322 auto& cur_dev = cur_icd.physical_devices.back();
5323 cur_dev.extensions.push_back({VK_KHR_DISPLAY_EXTENSION_NAME, 0});
5324
5325 // 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
5326 if ((icd == 0 && dev == 1) || icd == 3) {
5327 cur_dev.extensions.push_back({VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME, 0});
5328 device_version = VK_API_VERSION_1_1;
5329 }
5330
5331 // Still set physical device properties (so we can determine if device is correct API version)
5332 FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
5333 GenerateRandomDisplayModeProps(cur_dev.display_mode_properties);
5334 }
5335 }
5336
5337 InstWrapper instance(env.vulkan_functions);
5338 instance.create_info.add_extensions({VK_KHR_DISPLAY_EXTENSION_NAME, VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME});
5339 instance.CheckCreate();
5340
5341 PFN_vkGetDisplayModePropertiesKHR GetDisplayModePropertiesKHR = instance.load("vkGetDisplayModePropertiesKHR");
5342 ASSERT_NE(GetDisplayModePropertiesKHR, nullptr);
5343 PFN_vkGetDisplayModeProperties2KHR GetDisplayModeProperties2KHR = instance.load("vkGetDisplayModeProperties2KHR");
5344 ASSERT_NE(GetDisplayModeProperties2KHR, nullptr);
5345
5346 uint32_t device_count = max_phys_devs;
5347 std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
5348 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
5349 ASSERT_EQ(device_count, max_phys_devs);
5350
5351 for (uint32_t dev = 0; dev < device_count; ++dev) {
5352 std::vector<VkDisplayModePropertiesKHR> props{};
5353 uint32_t props_count1 = 0;
5354 ASSERT_EQ(VK_SUCCESS, GetDisplayModePropertiesKHR(physical_devices[dev], VK_NULL_HANDLE, &props_count1, nullptr));
5355 ASSERT_NE(0U, props_count1);
5356 props.resize(props_count1);
5357 ASSERT_EQ(VK_SUCCESS, GetDisplayModePropertiesKHR(physical_devices[dev], VK_NULL_HANDLE, &props_count1, props.data()));
5358
5359 std::vector<VkDisplayModeProperties2KHR> props2{};
5360 uint32_t props_count2 = 0;
5361 ASSERT_EQ(VK_SUCCESS, GetDisplayModeProperties2KHR(physical_devices[dev], VK_NULL_HANDLE, &props_count2, nullptr));
5362 ASSERT_EQ(props_count1, props_count2);
5363 props2.resize(props_count2, {VK_STRUCTURE_TYPE_DISPLAY_MODE_PROPERTIES_2_KHR});
5364 ASSERT_EQ(VK_SUCCESS, GetDisplayModeProperties2KHR(physical_devices[dev], VK_NULL_HANDLE, &props_count2, props2.data()));
5365
5366 ASSERT_TRUE(CompareDisplayModeProps(props, props2));
5367 }
5368 }
5369
5370 // Test vkGetDisplayPlaneCapabilities2KHR where nothing supports it.
TEST(LoaderInstPhysDevExts, GetDispPlaneCaps2KHRNoSupport)5371 TEST(LoaderInstPhysDevExts, GetDispPlaneCaps2KHRNoSupport) {
5372 FrameworkEnvironment env{};
5373 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
5374 env.get_test_icd(0).physical_devices.push_back({});
5375
5376 InstWrapper instance(env.vulkan_functions);
5377 instance.CheckCreate();
5378
5379 PFN_vkGetDisplayPlaneCapabilitiesKHR GetDisplayPlaneCapabilitiesKHR = instance.load("vkGetDisplayPlaneCapabilitiesKHR");
5380 ASSERT_EQ(GetDisplayPlaneCapabilitiesKHR, nullptr);
5381 }
5382
5383 // Test vkGetDisplayPlaneCapabilities2KHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, GetDispPlaneCaps2KHRNoICDSupport)5384 TEST(LoaderInstPhysDevExts, GetDispPlaneCaps2KHRNoICDSupport) {
5385 FrameworkEnvironment env{};
5386 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
5387 env.get_test_icd(0).physical_devices.push_back({});
5388
5389 InstWrapper instance(env.vulkan_functions);
5390 instance.create_info.add_extension(VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME);
5391 instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
5392
5393 PFN_vkGetDisplayPlaneCapabilitiesKHR GetDisplayPlaneCapabilitiesKHR = instance.load("vkGetDisplayPlaneCapabilitiesKHR");
5394 ASSERT_EQ(GetDisplayPlaneCapabilitiesKHR, nullptr);
5395 }
5396
5397 // Compare the display plane caps
CompareDisplayPlaneCaps(const VkDisplayPlaneCapabilitiesKHR& caps1, VkDisplayPlaneCapabilities2KHR& caps2)5398 bool CompareDisplayPlaneCaps(const VkDisplayPlaneCapabilitiesKHR& caps1, VkDisplayPlaneCapabilities2KHR& caps2) {
5399 bool equal = true;
5400 equal = equal && caps1.supportedAlpha == caps2.capabilities.supportedAlpha;
5401 equal = equal && caps1.minSrcPosition.x == caps2.capabilities.minSrcPosition.x;
5402 equal = equal && caps1.minSrcPosition.y == caps2.capabilities.minSrcPosition.y;
5403 equal = equal && caps1.maxSrcPosition.x == caps2.capabilities.maxSrcPosition.x;
5404 equal = equal && caps1.maxSrcPosition.y == caps2.capabilities.maxSrcPosition.y;
5405 equal = equal && caps1.minSrcExtent.width == caps2.capabilities.minSrcExtent.width;
5406 equal = equal && caps1.minSrcExtent.height == caps2.capabilities.minSrcExtent.height;
5407 equal = equal && caps1.maxSrcExtent.width == caps2.capabilities.maxSrcExtent.width;
5408 equal = equal && caps1.maxSrcExtent.height == caps2.capabilities.maxSrcExtent.height;
5409 equal = equal && caps1.minDstPosition.x == caps2.capabilities.minDstPosition.x;
5410 equal = equal && caps1.minDstPosition.y == caps2.capabilities.minDstPosition.y;
5411 equal = equal && caps1.maxDstPosition.x == caps2.capabilities.maxDstPosition.x;
5412 equal = equal && caps1.maxDstPosition.y == caps2.capabilities.maxDstPosition.y;
5413 equal = equal && caps1.minDstExtent.width == caps2.capabilities.minDstExtent.width;
5414 equal = equal && caps1.minDstExtent.height == caps2.capabilities.minDstExtent.height;
5415 equal = equal && caps1.maxDstExtent.width == caps2.capabilities.maxDstExtent.width;
5416 equal = equal && caps1.maxDstExtent.height == caps2.capabilities.maxDstExtent.height;
5417 return equal;
5418 }
5419
5420 // Test vkGetDisplayPlaneCapabilities2KHR where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, GetDispPlaneCaps2KHRInstanceAndICDSupport)5421 TEST(LoaderInstPhysDevExts, GetDispPlaneCaps2KHRInstanceAndICDSupport) {
5422 FrameworkEnvironment env{};
5423 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
5424 Extension first_ext{VK_KHR_DISPLAY_EXTENSION_NAME};
5425 Extension second_ext{VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME};
5426 env.get_test_icd(0).add_instance_extensions({first_ext, second_ext});
5427 env.get_test_icd(0).physical_devices.push_back({});
5428 FillInRandomDisplayPropData(env.get_test_icd(0).physical_devices.back().display_properties);
5429
5430 InstWrapper instance(env.vulkan_functions);
5431 instance.create_info.add_extensions({VK_KHR_DISPLAY_EXTENSION_NAME, VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME});
5432 instance.CheckCreate();
5433
5434 PFN_vkGetDisplayPlaneCapabilitiesKHR GetDisplayPlaneCapabilitiesKHR = instance.load("vkGetDisplayPlaneCapabilitiesKHR");
5435 ASSERT_NE(GetDisplayPlaneCapabilitiesKHR, nullptr);
5436 PFN_vkGetDisplayPlaneCapabilities2KHR GetDisplayPlaneCapabilities2KHR = instance.load("vkGetDisplayPlaneCapabilities2KHR");
5437 ASSERT_NE(GetDisplayPlaneCapabilities2KHR, nullptr);
5438
5439 uint32_t driver_count = 1;
5440 VkPhysicalDevice physical_device;
5441 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
5442 ASSERT_EQ(driver_count, 1U);
5443
5444 VkDisplayPlaneCapabilitiesKHR caps{};
5445 ASSERT_EQ(VK_SUCCESS, GetDisplayPlaneCapabilitiesKHR(physical_device, 0, 0, &caps));
5446 VkDisplayPlaneCapabilities2KHR caps2{};
5447 VkDisplayPlaneInfo2KHR info{VK_STRUCTURE_TYPE_DISPLAY_PLANE_INFO_2_KHR};
5448 ASSERT_EQ(VK_SUCCESS, GetDisplayPlaneCapabilities2KHR(physical_device, &info, &caps2));
5449 ASSERT_TRUE(CompareDisplayPlaneCaps(caps, caps2));
5450 }
5451
5452 // Test vkGetDisplayPlaneCapabilities2KHR where instance supports it with some ICDs that both support
5453 // and don't support it:
5454 // ICD 0 supports
5455 // Physical device 0 does not
5456 // Physical device 1 does
5457 // Physical device 2 does not
5458 // ICD 1 doesn't support
5459 // Physical device 3 does not
5460 // ICD 2 supports
5461 // Physical device 4 does not
5462 // Physical device 5 does not
5463 // ICD 3 supports
5464 // Physical device 6 does
TEST(LoaderInstPhysDevExts, GetDispPlaneCaps2KHRMixed)5465 TEST(LoaderInstPhysDevExts, GetDispPlaneCaps2KHRMixed) {
5466 FrameworkEnvironment env{};
5467 const uint32_t max_icd_count = 4;
5468 const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
5469 const uint32_t max_phys_devs = 7;
5470
5471 for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
5472 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, icd != 1 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0));
5473 auto& cur_icd = env.get_test_icd(icd);
5474 cur_icd.icd_api_version = VK_API_VERSION_1_0;
5475 cur_icd.add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
5476
5477 // ICD 1 should not have 1.1
5478 if (icd != 1) {
5479 cur_icd.icd_api_version = VK_API_VERSION_1_1;
5480 cur_icd.add_instance_extension({VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME});
5481 }
5482
5483 uint32_t rand_vendor_id;
5484 uint32_t rand_driver_vers;
5485 FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
5486
5487 for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
5488 uint32_t device_version = VK_API_VERSION_1_0;
5489 cur_icd.physical_devices.push_back({});
5490 auto& cur_dev = cur_icd.physical_devices.back();
5491 cur_dev.extensions.push_back({VK_KHR_DISPLAY_EXTENSION_NAME, 0});
5492
5493 // 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
5494 if ((icd == 0 && dev == 1) || icd == 3) {
5495 cur_dev.extensions.push_back({VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME, 0});
5496 device_version = VK_API_VERSION_1_1;
5497 }
5498
5499 // Still set physical device properties (so we can determine if device is correct API version)
5500 FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
5501 GenerateRandomDisplayPlaneCaps(cur_dev.display_plane_capabilities);
5502 }
5503 }
5504
5505 InstWrapper instance(env.vulkan_functions);
5506 instance.create_info.add_extensions({VK_KHR_DISPLAY_EXTENSION_NAME, VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME});
5507 instance.CheckCreate();
5508
5509 PFN_vkGetDisplayPlaneCapabilitiesKHR GetDisplayPlaneCapabilitiesKHR = instance.load("vkGetDisplayPlaneCapabilitiesKHR");
5510 ASSERT_NE(GetDisplayPlaneCapabilitiesKHR, nullptr);
5511 PFN_vkGetDisplayPlaneCapabilities2KHR GetDisplayPlaneCapabilities2KHR = instance.load("vkGetDisplayPlaneCapabilities2KHR");
5512 ASSERT_NE(GetDisplayPlaneCapabilities2KHR, nullptr);
5513
5514 uint32_t device_count = max_phys_devs;
5515 std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
5516 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
5517 ASSERT_EQ(device_count, max_phys_devs);
5518
5519 for (uint32_t dev = 0; dev < device_count; ++dev) {
5520 VkDisplayPlaneCapabilitiesKHR caps{};
5521 ASSERT_EQ(VK_SUCCESS, GetDisplayPlaneCapabilitiesKHR(physical_devices[dev], 0, 0, &caps));
5522 VkDisplayPlaneCapabilities2KHR caps2{};
5523 VkDisplayPlaneInfo2KHR info{VK_STRUCTURE_TYPE_DISPLAY_PLANE_INFO_2_KHR};
5524 ASSERT_EQ(VK_SUCCESS, GetDisplayPlaneCapabilities2KHR(physical_devices[dev], &info, &caps2));
5525 CompareDisplayPlaneCaps(caps, caps2);
5526 }
5527 }
5528
5529 //
5530 // VK_EXT_acquire_drm_display
5531 //
5532
5533 // Test vkAcquireDrmDisplayEXT where nothing supports it.
TEST(LoaderInstPhysDevExts, AcquireDrmDisplayEXTNoSupport)5534 TEST(LoaderInstPhysDevExts, AcquireDrmDisplayEXTNoSupport) {
5535 FrameworkEnvironment env{};
5536 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
5537 env.get_test_icd(0).physical_devices.push_back({});
5538
5539 InstWrapper instance(env.vulkan_functions);
5540 instance.CheckCreate();
5541
5542 PFN_vkAcquireDrmDisplayEXT AcquireDrmDisplayEXT = instance.load("vkAcquireDrmDisplayEXT");
5543 ASSERT_EQ(AcquireDrmDisplayEXT, nullptr);
5544 }
5545
5546 // Test vkAcquireDrmDisplayEXT where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, AcquireDrmDisplayEXTNoICDSupport)5547 TEST(LoaderInstPhysDevExts, AcquireDrmDisplayEXTNoICDSupport) {
5548 FrameworkEnvironment env{};
5549 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
5550 env.get_test_icd(0).physical_devices.push_back({});
5551
5552 InstWrapper instance(env.vulkan_functions);
5553 instance.create_info.add_extension(VK_EXT_ACQUIRE_DRM_DISPLAY_EXTENSION_NAME);
5554 instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
5555
5556 PFN_vkAcquireDrmDisplayEXT AcquireDrmDisplayEXT = instance.load("vkAcquireDrmDisplayEXT");
5557 ASSERT_EQ(AcquireDrmDisplayEXT, nullptr);
5558 }
5559
5560 // Test vkAcquireDrmDisplayEXT where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, AcquireDrmDisplayEXTInstanceAndICDSupport)5561 TEST(LoaderInstPhysDevExts, AcquireDrmDisplayEXTInstanceAndICDSupport) {
5562 FrameworkEnvironment env{};
5563 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
5564 Extension first_ext{VK_KHR_DISPLAY_EXTENSION_NAME};
5565 Extension second_ext{VK_EXT_ACQUIRE_DRM_DISPLAY_EXTENSION_NAME};
5566 env.get_test_icd(0).add_instance_extensions({first_ext, second_ext});
5567 env.get_test_icd(0).physical_devices.push_back({});
5568 GenerateRandomDisplays(env.get_test_icd(0).physical_devices.back().displays);
5569
5570 InstWrapper instance(env.vulkan_functions);
5571 instance.create_info.add_extensions({VK_KHR_DISPLAY_EXTENSION_NAME, VK_EXT_ACQUIRE_DRM_DISPLAY_EXTENSION_NAME});
5572 instance.CheckCreate();
5573
5574 PFN_vkAcquireDrmDisplayEXT AcquireDrmDisplayEXT = instance.load("vkAcquireDrmDisplayEXT");
5575 ASSERT_NE(AcquireDrmDisplayEXT, nullptr);
5576
5577 uint32_t driver_count = 1;
5578 VkPhysicalDevice physical_device;
5579 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
5580 ASSERT_EQ(driver_count, 1U);
5581
5582 VkDisplayKHR display = VK_NULL_HANDLE;
5583 ASSERT_EQ(VK_SUCCESS, AcquireDrmDisplayEXT(physical_device, 0, display));
5584 }
5585
5586 // Test vkAcquireDrmDisplayEXT where instance supports it with some ICDs that both support
5587 // and don't support it:
5588 // ICD 0 supports
5589 // Physical device 0 does not
5590 // Physical device 1 does
5591 // Physical device 2 does not
5592 // ICD 1 doesn't support
5593 // Physical device 3 does not
5594 // ICD 2 supports
5595 // Physical device 4 does not
5596 // Physical device 5 does not
5597 // ICD 3 supports
5598 // Physical device 6 does
TEST(LoaderInstPhysDevExts, AcquireDrmDisplayEXTMixed)5599 TEST(LoaderInstPhysDevExts, AcquireDrmDisplayEXTMixed) {
5600 FrameworkEnvironment env{};
5601 const uint32_t max_icd_count = 4;
5602 const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
5603 const uint32_t max_phys_devs = 7;
5604
5605 for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
5606 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, icd != 1 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0));
5607 auto& cur_icd = env.get_test_icd(icd);
5608 cur_icd.icd_api_version = VK_API_VERSION_1_0;
5609 cur_icd.add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
5610
5611 // ICD 1 should not have 1.1
5612 if (icd != 1) {
5613 cur_icd.icd_api_version = VK_API_VERSION_1_1;
5614 cur_icd.add_instance_extension({VK_EXT_ACQUIRE_DRM_DISPLAY_EXTENSION_NAME});
5615 }
5616
5617 uint32_t rand_vendor_id;
5618 uint32_t rand_driver_vers;
5619 FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
5620
5621 for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
5622 uint32_t device_version = VK_API_VERSION_1_0;
5623 cur_icd.physical_devices.push_back({});
5624 auto& cur_dev = cur_icd.physical_devices.back();
5625 cur_dev.extensions.push_back({VK_KHR_DISPLAY_EXTENSION_NAME, 0});
5626
5627 // 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
5628 if ((icd == 0 && dev == 1) || icd == 3) {
5629 cur_dev.extensions.push_back({VK_EXT_ACQUIRE_DRM_DISPLAY_EXTENSION_NAME, 0});
5630 device_version = VK_API_VERSION_1_1;
5631 }
5632
5633 // Still set physical device properties (so we can determine if device is correct API version)
5634 FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
5635 GenerateRandomDisplays(cur_dev.displays);
5636 }
5637 }
5638
5639 InstWrapper instance(env.vulkan_functions);
5640 instance.create_info.add_extensions({VK_KHR_DISPLAY_EXTENSION_NAME, VK_EXT_ACQUIRE_DRM_DISPLAY_EXTENSION_NAME});
5641 instance.CheckCreate();
5642
5643 PFN_vkAcquireDrmDisplayEXT AcquireDrmDisplayEXT = instance.load("vkAcquireDrmDisplayEXT");
5644 ASSERT_NE(AcquireDrmDisplayEXT, nullptr);
5645
5646 uint32_t device_count = max_phys_devs;
5647 std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
5648 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
5649 ASSERT_EQ(device_count, max_phys_devs);
5650
5651 for (uint32_t dev = 0; dev < device_count; ++dev) {
5652 VkPhysicalDeviceProperties pd_props{};
5653 instance->vkGetPhysicalDeviceProperties(physical_devices[dev], &pd_props);
5654
5655 for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
5656 auto& cur_icd = env.get_test_icd(icd);
5657 bool found = false;
5658 for (uint32_t pd = 0; pd < dev_counts[icd]; ++pd) {
5659 auto& cur_dev = cur_icd.physical_devices[pd];
5660 // Find the ICD device matching the physical device we're looking at info for so we can compare the
5661 // physical devices info with the returned info.
5662 if (cur_dev.properties.apiVersion == pd_props.apiVersion && cur_dev.properties.deviceID == pd_props.deviceID &&
5663 cur_dev.properties.deviceType == pd_props.deviceType &&
5664 cur_dev.properties.driverVersion == pd_props.driverVersion &&
5665 cur_dev.properties.vendorID == pd_props.vendorID) {
5666 VkDisplayKHR display = VK_NULL_HANDLE;
5667 if (icd == 1) {
5668 // For this extension, if no support exists (like for ICD 1), the value of 0 should be returned by the
5669 // loader.
5670 ASSERT_EQ(VK_ERROR_EXTENSION_NOT_PRESENT, AcquireDrmDisplayEXT(physical_devices[dev], 0, display));
5671 } else {
5672 ASSERT_EQ(VK_SUCCESS, AcquireDrmDisplayEXT(physical_devices[dev], 0, display));
5673 }
5674 found = true;
5675 break;
5676 }
5677 }
5678 if (found) {
5679 break;
5680 }
5681 }
5682 }
5683 }
5684
5685 // Test vkGetDrmDisplayEXT where nothing supports it.
TEST(LoaderInstPhysDevExts, GetDrmDisplayEXTNoSupport)5686 TEST(LoaderInstPhysDevExts, GetDrmDisplayEXTNoSupport) {
5687 FrameworkEnvironment env{};
5688 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
5689 env.get_test_icd(0).physical_devices.push_back({});
5690
5691 InstWrapper instance(env.vulkan_functions);
5692 instance.CheckCreate();
5693
5694 PFN_vkGetDrmDisplayEXT GetDrmDisplayEXT = instance.load("vkGetDrmDisplayEXT");
5695 ASSERT_EQ(GetDrmDisplayEXT, nullptr);
5696 }
5697
5698 // Test vkGetDrmDisplayEXT where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, GetDrmDisplayEXTNoICDSupport)5699 TEST(LoaderInstPhysDevExts, GetDrmDisplayEXTNoICDSupport) {
5700 FrameworkEnvironment env{};
5701 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
5702 env.get_test_icd(0).physical_devices.push_back({});
5703
5704 InstWrapper instance(env.vulkan_functions);
5705 instance.create_info.add_extension(VK_EXT_ACQUIRE_DRM_DISPLAY_EXTENSION_NAME);
5706 instance.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
5707
5708 PFN_vkGetDrmDisplayEXT GetDrmDisplayEXT = instance.load("vkGetDrmDisplayEXT");
5709 ASSERT_EQ(GetDrmDisplayEXT, nullptr);
5710 }
5711
5712 // Test vkGetDrmDisplayEXT where instance and ICD supports it, but device does not support it.
TEST(LoaderInstPhysDevExts, GetDrmDisplayEXTInstanceAndICDSupport)5713 TEST(LoaderInstPhysDevExts, GetDrmDisplayEXTInstanceAndICDSupport) {
5714 FrameworkEnvironment env{};
5715 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
5716 Extension first_ext{VK_KHR_DISPLAY_EXTENSION_NAME};
5717 Extension second_ext{VK_EXT_ACQUIRE_DRM_DISPLAY_EXTENSION_NAME};
5718 env.get_test_icd(0).add_instance_extensions({first_ext, second_ext});
5719 env.get_test_icd(0).physical_devices.push_back({});
5720 GenerateRandomDisplays(env.get_test_icd(0).physical_devices.back().displays);
5721
5722 InstWrapper instance(env.vulkan_functions);
5723 instance.create_info.add_extensions({VK_KHR_DISPLAY_EXTENSION_NAME, VK_EXT_ACQUIRE_DRM_DISPLAY_EXTENSION_NAME});
5724 instance.CheckCreate();
5725
5726 PFN_vkGetDrmDisplayEXT GetDrmDisplayEXT = instance.load("vkGetDrmDisplayEXT");
5727 ASSERT_NE(GetDrmDisplayEXT, nullptr);
5728
5729 uint32_t driver_count = 1;
5730 VkPhysicalDevice physical_device;
5731 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
5732 ASSERT_EQ(driver_count, 1U);
5733
5734 VkDisplayKHR display = VK_NULL_HANDLE;
5735 ASSERT_EQ(VK_SUCCESS, GetDrmDisplayEXT(physical_device, 0, 0, &display));
5736 ASSERT_EQ(display, env.get_test_icd(0).physical_devices.back().displays[0]);
5737 }
5738
5739 // Test vkGetDrmDisplayEXT where instance supports it with some ICDs that both support
5740 // and don't support it:
5741 // ICD 0 supports
5742 // Physical device 0 does not
5743 // Physical device 1 does
5744 // Physical device 2 does not
5745 // ICD 1 doesn't support
5746 // Physical device 3 does not
5747 // ICD 2 supports
5748 // Physical device 4 does not
5749 // Physical device 5 does not
5750 // ICD 3 supports
5751 // Physical device 6 does
TEST(LoaderInstPhysDevExts, GetDrmDisplayEXTMixed)5752 TEST(LoaderInstPhysDevExts, GetDrmDisplayEXTMixed) {
5753 FrameworkEnvironment env{};
5754 const uint32_t max_icd_count = 4;
5755 const uint32_t dev_counts[max_icd_count] = {3, 1, 2, 1};
5756 const uint32_t max_phys_devs = 7;
5757
5758 for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
5759 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, icd != 1 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0));
5760 auto& cur_icd = env.get_test_icd(icd);
5761 cur_icd.icd_api_version = VK_API_VERSION_1_0;
5762 cur_icd.add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
5763
5764 // ICD 1 should not have 1.1
5765 if (icd != 1) {
5766 cur_icd.icd_api_version = VK_API_VERSION_1_1;
5767 cur_icd.add_instance_extension({VK_EXT_ACQUIRE_DRM_DISPLAY_EXTENSION_NAME});
5768 }
5769
5770 uint32_t rand_vendor_id;
5771 uint32_t rand_driver_vers;
5772 FillInRandomICDInfo(rand_vendor_id, rand_driver_vers);
5773
5774 for (uint32_t dev = 0; dev < dev_counts[icd]; ++dev) {
5775 uint32_t device_version = VK_API_VERSION_1_0;
5776 cur_icd.physical_devices.push_back({});
5777 auto& cur_dev = cur_icd.physical_devices.back();
5778 cur_dev.extensions.push_back({VK_KHR_DISPLAY_EXTENSION_NAME, 0});
5779
5780 // 2nd device in ICD 0 and the one device in ICD 3 support the extension and 1.1
5781 if ((icd == 0 && dev == 1) || icd == 3) {
5782 cur_dev.extensions.push_back({VK_EXT_ACQUIRE_DRM_DISPLAY_EXTENSION_NAME, 0});
5783 device_version = VK_API_VERSION_1_1;
5784 }
5785
5786 // Still set physical device properties (so we can determine if device is correct API version)
5787 FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
5788 GenerateRandomDisplays(cur_dev.displays);
5789 }
5790 }
5791
5792 InstWrapper instance(env.vulkan_functions);
5793 instance.create_info.add_extensions({VK_KHR_DISPLAY_EXTENSION_NAME, VK_EXT_ACQUIRE_DRM_DISPLAY_EXTENSION_NAME});
5794 instance.CheckCreate();
5795
5796 PFN_vkGetDrmDisplayEXT GetDrmDisplayEXT = instance.load("vkGetDrmDisplayEXT");
5797 ASSERT_NE(GetDrmDisplayEXT, nullptr);
5798
5799 uint32_t device_count = max_phys_devs;
5800 std::array<VkPhysicalDevice, max_phys_devs> physical_devices;
5801 ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &device_count, physical_devices.data()));
5802 ASSERT_EQ(device_count, max_phys_devs);
5803
5804 for (uint32_t dev = 0; dev < device_count; ++dev) {
5805 VkPhysicalDeviceProperties pd_props{};
5806 instance->vkGetPhysicalDeviceProperties(physical_devices[dev], &pd_props);
5807
5808 for (uint32_t icd = 0; icd < max_icd_count; ++icd) {
5809 auto& cur_icd = env.get_test_icd(icd);
5810 bool found = false;
5811 for (uint32_t pd = 0; pd < dev_counts[icd]; ++pd) {
5812 auto& cur_dev = cur_icd.physical_devices[pd];
5813 // Find the ICD device matching the physical device we're looking at info for so we can compare the
5814 // physical devices info with the returned info.
5815 if (cur_dev.properties.apiVersion == pd_props.apiVersion && cur_dev.properties.deviceID == pd_props.deviceID &&
5816 cur_dev.properties.deviceType == pd_props.deviceType &&
5817 cur_dev.properties.driverVersion == pd_props.driverVersion &&
5818 cur_dev.properties.vendorID == pd_props.vendorID) {
5819 VkDisplayKHR display = VK_NULL_HANDLE;
5820 if (icd == 1) {
5821 // For this extension, if no support exists (like for ICD 1), the value of 0 should be returned by the
5822 // loader.
5823 ASSERT_EQ(VK_ERROR_EXTENSION_NOT_PRESENT, GetDrmDisplayEXT(physical_devices[dev], 0, 0, &display));
5824 } else {
5825 ASSERT_EQ(VK_SUCCESS, GetDrmDisplayEXT(physical_devices[dev], 0, 0, &display));
5826 ASSERT_EQ(display, cur_dev.displays[0]);
5827 }
5828 found = true;
5829 break;
5830 }
5831 }
5832 if (found) {
5833 break;
5834 }
5835 }
5836 }
5837 }
5838
TEST(LoaderInstPhysDevExts, DifferentInstanceExtensions)5839 TEST(LoaderInstPhysDevExts, DifferentInstanceExtensions) {
5840 FrameworkEnvironment env{};
5841
5842 // Add 3 drivers each of which supports a different instance extension
5843 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_0));
5844 env.get_test_icd(0).add_instance_extension({VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME});
5845 env.get_test_icd(0).physical_devices.push_back({"pd0"});
5846 env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME, 0});
5847
5848 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_0));
5849 env.get_test_icd(1).add_instance_extension({VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME});
5850 env.get_test_icd(1).physical_devices.push_back({"pd1"});
5851 env.get_test_icd(1).physical_devices.back().extensions.push_back({VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME, 0});
5852
5853 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_0));
5854 env.get_test_icd(2).add_instance_extension({VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME});
5855 env.get_test_icd(2).physical_devices.push_back({"pd2"});
5856 env.get_test_icd(2).physical_devices.back().extensions.push_back({VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME, 0});
5857
5858 DebugUtilsLogger log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
5859 InstWrapper inst{env.vulkan_functions};
5860 inst.create_info.add_extensions({VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,
5861 VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME,
5862 VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME});
5863 FillDebugUtilsCreateDetails(inst.create_info, log);
5864 inst.CheckCreate();
5865
5866 const uint32_t expected_device_count = 3;
5867 auto physical_devices = inst.GetPhysDevs(expected_device_count);
5868
5869 PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR GetPhysicalDeviceExternalBufferProperties =
5870 inst.load("vkGetPhysicalDeviceExternalBufferPropertiesKHR");
5871 PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR GetPhysicalDeviceExternalSemaphoreProperties =
5872 inst.load("vkGetPhysicalDeviceExternalSemaphorePropertiesKHR");
5873 PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR GetPhysicalDeviceExternalFenceProperties =
5874 inst.load("vkGetPhysicalDeviceExternalFencePropertiesKHR");
5875 ASSERT_NE(nullptr, GetPhysicalDeviceExternalBufferProperties);
5876 ASSERT_NE(nullptr, GetPhysicalDeviceExternalSemaphoreProperties);
5877 ASSERT_NE(nullptr, GetPhysicalDeviceExternalFenceProperties);
5878
5879 // The above are instance extensions, so shouldn't crash even if only one physical device supports each
5880 // extension.
5881 for (uint32_t dev = 0; dev < expected_device_count; ++dev) {
5882 VkPhysicalDeviceExternalBufferInfo ext_buf_info{};
5883 VkExternalBufferProperties ext_buf_props{};
5884 VkPhysicalDeviceExternalSemaphoreInfo ext_sem_info{};
5885 VkExternalSemaphoreProperties ext_sem_props{};
5886 VkPhysicalDeviceExternalFenceInfo ext_fence_info{};
5887 VkExternalFenceProperties ext_fence_props{};
5888 GetPhysicalDeviceExternalBufferProperties(physical_devices[dev], &ext_buf_info, &ext_buf_props);
5889 GetPhysicalDeviceExternalSemaphoreProperties(physical_devices[dev], &ext_sem_info, &ext_sem_props);
5890 GetPhysicalDeviceExternalFenceProperties(physical_devices[dev], &ext_fence_info, &ext_fence_props);
5891 }
5892 }
5893
TEST(LoaderInstPhysDevExts, DifferentPhysicalDeviceExtensions)5894 TEST(LoaderInstPhysDevExts, DifferentPhysicalDeviceExtensions) {
5895 FrameworkEnvironment env{};
5896
5897 // Add 3 drivers each of which supports a different physical device extension
5898 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_0));
5899 env.get_test_icd(0).physical_devices.push_back("pd0");
5900 env.get_test_icd(0).physical_devices.back().extensions.push_back({VK_KHR_PERFORMANCE_QUERY_EXTENSION_NAME, 0});
5901
5902 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_0));
5903 env.get_test_icd(1).physical_devices.push_back("pd1");
5904 env.get_test_icd(1).physical_devices.back().extensions.push_back({VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME, 0});
5905
5906 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_0));
5907 env.get_test_icd(2).physical_devices.push_back("pd2");
5908 env.get_test_icd(2).physical_devices.back().extensions.push_back({VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME, 0});
5909
5910 DebugUtilsLogger log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
5911 InstWrapper inst{env.vulkan_functions};
5912 FillDebugUtilsCreateDetails(inst.create_info, log);
5913 inst.CheckCreate();
5914
5915 const uint32_t expected_device_count = 3;
5916 auto physical_devices = inst.GetPhysDevs(expected_device_count);
5917
5918 PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR
5919 EnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR =
5920 inst.load("vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR");
5921 PFN_vkGetPhysicalDeviceMultisamplePropertiesEXT GetPhysicalDeviceMultisamplePropertiesEXT =
5922 inst.load("vkGetPhysicalDeviceMultisamplePropertiesEXT");
5923 PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT GetPhysicalDeviceCalibrateableTimeDomainsEXT =
5924 inst.load("vkGetPhysicalDeviceCalibrateableTimeDomainsEXT");
5925 ASSERT_NE(nullptr, EnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR);
5926 ASSERT_NE(nullptr, GetPhysicalDeviceMultisamplePropertiesEXT);
5927 ASSERT_NE(nullptr, GetPhysicalDeviceCalibrateableTimeDomainsEXT);
5928
5929 for (uint32_t dev = 0; dev < expected_device_count; ++dev) {
5930 uint32_t extension_count = 0;
5931 std::vector<VkExtensionProperties> device_extensions;
5932 bool supports_query = false;
5933 bool supports_samples = false;
5934 bool supports_timestamps = false;
5935 ASSERT_EQ(VK_SUCCESS,
5936 inst->vkEnumerateDeviceExtensionProperties(physical_devices[dev], nullptr, &extension_count, nullptr));
5937 ASSERT_GT(extension_count, 0U);
5938 device_extensions.resize(extension_count);
5939 ASSERT_EQ(VK_SUCCESS, inst->vkEnumerateDeviceExtensionProperties(physical_devices[dev], nullptr, &extension_count,
5940 device_extensions.data()));
5941 for (uint32_t ext = 0; ext < extension_count; ++ext) {
5942 if (string_eq(VK_KHR_PERFORMANCE_QUERY_EXTENSION_NAME, &device_extensions[ext].extensionName[0])) {
5943 supports_query = true;
5944 }
5945 if (string_eq(VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME, &device_extensions[ext].extensionName[0])) {
5946 supports_samples = true;
5947 }
5948 if (string_eq(VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME, &device_extensions[ext].extensionName[0])) {
5949 supports_timestamps = true;
5950 }
5951 }
5952
5953 // For physical device extensions, they should work for devices that support it and crash for those that don't.
5954 if (supports_query) {
5955 ASSERT_EQ(VK_SUCCESS, EnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR(physical_devices[dev], 0, nullptr,
5956 nullptr, nullptr));
5957 } else {
5958 ASSERT_DEATH(
5959 EnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR(physical_devices[dev], 0, nullptr, nullptr, nullptr),
5960 "");
5961 ASSERT_FALSE(
5962 log.find("ICD associated with VkPhysicalDevice does not support "
5963 "EnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR"));
5964 }
5965 if (supports_samples) {
5966 GetPhysicalDeviceMultisamplePropertiesEXT(physical_devices[dev], VK_SAMPLE_COUNT_2_BIT, nullptr);
5967 } else {
5968 ASSERT_DEATH(GetPhysicalDeviceMultisamplePropertiesEXT(physical_devices[dev], VK_SAMPLE_COUNT_2_BIT, nullptr), "");
5969 ASSERT_FALSE(
5970 log.find("ICD associated with VkPhysicalDevice does not support GetPhysicalDeviceMultisamplePropertiesEXT"));
5971 }
5972 if (supports_timestamps) {
5973 ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceCalibrateableTimeDomainsEXT(physical_devices[dev], nullptr, nullptr));
5974 } else {
5975 ASSERT_DEATH(GetPhysicalDeviceCalibrateableTimeDomainsEXT(physical_devices[dev], nullptr, nullptr), "");
5976 ASSERT_FALSE(
5977 log.find("ICD associated with VkPhysicalDevice does not support GetPhysicalDeviceCalibrateableTimeDomainsEXT"));
5978 }
5979 }
5980 }
5981