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