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