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