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 */
27
28 #include "test_environment.h"
29
30 class WsiTests : public ::testing::Test {};
31
32 #if defined(VK_USE_PLATFORM_WIN32_KHR)
33
34 // When ICD doesn't support the extension, create instance should fail
TEST(WsiTests,CreateSurfaceWin32NoICDSupport)35 TEST(WsiTests, CreateSurfaceWin32NoICDSupport) {
36 FrameworkEnvironment env{};
37 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
38 auto& cur_icd = env.get_test_icd(0);
39 cur_icd.set_min_icd_interface_version(5);
40
41 InstWrapper inst{env.vulkan_functions};
42 inst.create_info.add_extensions({VK_KHR_WIN32_SURFACE_EXTENSION_NAME});
43 inst.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
44
45 InstWrapper inst2{env.vulkan_functions};
46 inst2.CheckCreate();
47
48 ASSERT_EQ(nullptr, env.vulkan_functions.vkGetInstanceProcAddr(inst2.inst, "vkCreateWin32SurfaceKHR"));
49 }
50
51 // When ICD doesn't support the surface creation, the loader should handle it
TEST(WsiTests,CreateSurfaceWin32NoICDCreateSupport)52 TEST(WsiTests, CreateSurfaceWin32NoICDCreateSupport) {
53 FrameworkEnvironment env{};
54 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
55 auto& cur_icd = env.get_test_icd(0);
56 cur_icd.set_min_icd_interface_version(5);
57 cur_icd.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME});
58 cur_icd.add_instance_extension({VK_KHR_WIN32_SURFACE_EXTENSION_NAME});
59 cur_icd.enable_icd_wsi = false;
60
61 InstWrapper inst{env.vulkan_functions};
62 inst.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WIN32_SURFACE_EXTENSION_NAME});
63 inst.CheckCreate();
64
65 VkSurfaceKHR surface{VK_NULL_HANDLE};
66 VkWin32SurfaceCreateInfoKHR surf_create_info{VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR};
67 ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateWin32SurfaceKHR(inst, &surf_create_info, nullptr, &surface));
68 ASSERT_TRUE(surface != VK_NULL_HANDLE);
69
70 env.vulkan_functions.vkDestroySurfaceKHR(inst, surface, nullptr);
71 }
72
73 // When ICD does support the surface creation, the loader should delegat handle it to the ICD
TEST(WsiTests,CreateSurfaceWin32ICDSupport)74 TEST(WsiTests, CreateSurfaceWin32ICDSupport) {
75 FrameworkEnvironment env{};
76 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
77 auto& cur_icd = env.get_test_icd(0);
78 cur_icd.set_min_icd_interface_version(5);
79 cur_icd.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME});
80 cur_icd.add_instance_extension({VK_KHR_WIN32_SURFACE_EXTENSION_NAME});
81 cur_icd.enable_icd_wsi = true;
82
83 InstWrapper inst{env.vulkan_functions};
84 inst.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WIN32_SURFACE_EXTENSION_NAME});
85 inst.CheckCreate();
86
87 VkSurfaceKHR surface{VK_NULL_HANDLE};
88 VkWin32SurfaceCreateInfoKHR surf_create_info{VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR};
89 ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateWin32SurfaceKHR(inst, &surf_create_info, nullptr, &surface));
90 ASSERT_TRUE(surface != VK_NULL_HANDLE);
91
92 env.vulkan_functions.vkDestroySurfaceKHR(inst, surface, nullptr);
93 }
94
95 // Some drivers supporting vkCreateWin32SurfaceKHR, and at least one that doesn't
TEST(WsiTests,CreateSurfaceWin32MixedICDSupport)96 TEST(WsiTests, CreateSurfaceWin32MixedICDSupport) {
97 FrameworkEnvironment env{};
98 for (uint32_t icd = 0; icd < 3; ++icd) {
99 Extension first_ext{VK_KHR_SURFACE_EXTENSION_NAME};
100 Extension second_ext{VK_KHR_WIN32_SURFACE_EXTENSION_NAME};
101 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
102 auto& cur_icd = env.get_test_icd(icd);
103 cur_icd.icd_api_version = VK_API_VERSION_1_0;
104 cur_icd.add_instance_extensions({first_ext, second_ext});
105 if (icd < 2) {
106 // Only enable ICD for first two
107 cur_icd.enable_icd_wsi = true;
108 }
109 }
110
111 InstWrapper instance(env.vulkan_functions);
112 instance.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WIN32_SURFACE_EXTENSION_NAME});
113 instance.CheckCreate();
114
115 VkSurfaceKHR surface{VK_NULL_HANDLE};
116 VkWin32SurfaceCreateInfoKHR surf_create_info{VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR};
117 ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateWin32SurfaceKHR(instance.inst, &surf_create_info, nullptr, &surface));
118 ASSERT_TRUE(surface != VK_NULL_HANDLE);
119
120 env.vulkan_functions.vkDestroySurfaceKHR(instance.inst, surface, nullptr);
121 }
122
TEST(WsiTests,GetPhysicalDeviceWin32PresentNoICDSupport)123 TEST(WsiTests, GetPhysicalDeviceWin32PresentNoICDSupport) {
124 FrameworkEnvironment env{};
125 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
126 auto& cur_icd = env.get_test_icd(0);
127 cur_icd.set_min_icd_interface_version(5);
128 cur_icd.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME});
129 cur_icd.add_instance_extension({VK_KHR_WIN32_SURFACE_EXTENSION_NAME});
130 cur_icd.physical_devices.emplace_back("physical_device_0");
131 cur_icd.enable_icd_wsi = false;
132
133 InstWrapper inst{env.vulkan_functions};
134 inst.create_info.add_extensions(
135 {VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WIN32_SURFACE_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_EXTENSION_NAME});
136 inst.CheckCreate();
137
138 uint32_t driver_count = 1;
139 VkPhysicalDevice physical_device;
140 ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &driver_count, &physical_device));
141 ASSERT_EQ(driver_count, 1U);
142
143 DebugUtilsWrapper log{inst};
144 CreateDebugUtilsMessenger(log);
145 auto res = env.vulkan_functions.vkGetPhysicalDeviceWin32PresentationSupportKHR(physical_device, 0);
146 ASSERT_EQ(res, VK_FALSE);
147 ASSERT_TRUE(log.find("ICD for selected physical device does not export vkGetPhysicalDeviceWin32PresentationSupportKHR!"));
148 }
149
TEST(WsiTests,GetPhysicalDeviceWin32PresentICDSupport)150 TEST(WsiTests, GetPhysicalDeviceWin32PresentICDSupport) {
151 FrameworkEnvironment env{};
152 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
153 auto& cur_icd = env.get_test_icd(0);
154 cur_icd.set_min_icd_interface_version(5);
155 cur_icd.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME});
156 cur_icd.add_instance_extension({VK_KHR_WIN32_SURFACE_EXTENSION_NAME});
157 cur_icd.physical_devices.emplace_back("physical_device_0");
158 cur_icd.enable_icd_wsi = true;
159
160 InstWrapper inst{env.vulkan_functions};
161 inst.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WIN32_SURFACE_EXTENSION_NAME});
162 inst.CheckCreate();
163
164 uint32_t driver_count = 1;
165 VkPhysicalDevice physical_device;
166 ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &driver_count, &physical_device));
167 ASSERT_EQ(driver_count, 1U);
168
169 ASSERT_EQ(VK_TRUE, env.vulkan_functions.vkGetPhysicalDeviceWin32PresentationSupportKHR(physical_device, 0));
170 }
171
TEST(WsiTests,Win32GetPhysicalDeviceSurfaceSupportKHR)172 TEST(WsiTests, Win32GetPhysicalDeviceSurfaceSupportKHR) {
173 FrameworkEnvironment env{};
174 const uint32_t max_device_count = 4;
175 for (uint32_t icd = 0; icd < max_device_count; ++icd) {
176 Extension first_ext{VK_KHR_SURFACE_EXTENSION_NAME};
177 Extension second_ext{VK_KHR_WIN32_SURFACE_EXTENSION_NAME};
178 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
179 auto& cur_icd = env.get_test_icd(icd);
180 cur_icd.icd_api_version = VK_API_VERSION_1_0;
181 cur_icd.set_min_icd_interface_version(5);
182 cur_icd.add_instance_extensions({first_ext, second_ext});
183 std::string dev_name = "phys_dev_" + std::to_string(icd);
184 cur_icd.physical_devices.emplace_back(dev_name.c_str());
185 cur_icd.physical_devices.back().add_queue_family_properties({{VK_QUEUE_GRAPHICS_BIT, 1, 0, {1, 1, 1}}, true});
186 cur_icd.enable_icd_wsi = true;
187 }
188
189 InstWrapper instance(env.vulkan_functions);
190 instance.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WIN32_SURFACE_EXTENSION_NAME});
191 instance.CheckCreate();
192
193 VkSurfaceKHR surface{VK_NULL_HANDLE};
194 VkWin32SurfaceCreateInfoKHR surf_create_info{VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR};
195 ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateWin32SurfaceKHR(instance.inst, &surf_create_info, nullptr, &surface));
196 ASSERT_TRUE(surface != VK_NULL_HANDLE);
197
198 uint32_t device_count = max_device_count;
199 std::array<VkPhysicalDevice, max_device_count> phys_devs;
200 ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumeratePhysicalDevices(instance.inst, &device_count, phys_devs.data()));
201 ASSERT_EQ(device_count, max_device_count);
202
203 for (uint32_t pd = 0; pd < max_device_count; ++pd) {
204 VkBool32 supported = VK_FALSE;
205 ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkGetPhysicalDeviceSurfaceSupportKHR(phys_devs[pd], 0, surface, &supported));
206 }
207
208 env.vulkan_functions.vkDestroySurfaceKHR(instance.inst, surface, nullptr);
209 }
210 #endif
211
212 #if defined(VK_USE_PLATFORM_XCB_KHR)
213 // When ICD doesn't support the extension, create instance should fail
TEST(WsiTests,CreateSurfaceXCBNoICDSupport)214 TEST(WsiTests, CreateSurfaceXCBNoICDSupport) {
215 FrameworkEnvironment env{};
216 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
217 auto& cur_icd = env.get_test_icd(0);
218 cur_icd.set_min_icd_interface_version(5);
219 cur_icd.enable_icd_wsi = false;
220
221 InstWrapper inst{env.vulkan_functions};
222 inst.create_info.add_extensions({VK_KHR_XCB_SURFACE_EXTENSION_NAME});
223 inst.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
224
225 InstWrapper inst2{env.vulkan_functions};
226 inst2.CheckCreate();
227
228 ASSERT_EQ(nullptr, env.vulkan_functions.vkGetInstanceProcAddr(inst2.inst, "vkCreateXcbSurfaceKHR"));
229 }
230
231 // When ICD doesn't support the surface creation, the loader should handle it
TEST(WsiTests,CreateSurfaceXCBNoICDCreateSupport)232 TEST(WsiTests, CreateSurfaceXCBNoICDCreateSupport) {
233 FrameworkEnvironment env{};
234 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
235 auto& cur_icd = env.get_test_icd(0);
236 cur_icd.set_min_icd_interface_version(5);
237 cur_icd.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME});
238 cur_icd.add_instance_extension({VK_KHR_XCB_SURFACE_EXTENSION_NAME});
239 cur_icd.enable_icd_wsi = false;
240
241 InstWrapper inst{env.vulkan_functions};
242 inst.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_XCB_SURFACE_EXTENSION_NAME});
243 inst.CheckCreate();
244
245 VkXcbSurfaceCreateInfoKHR xcb_createInfo{VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR};
246
247 VkSurfaceKHR surface{VK_NULL_HANDLE};
248 ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateXcbSurfaceKHR(inst, &xcb_createInfo, nullptr, &surface));
249 ASSERT_TRUE(surface != VK_NULL_HANDLE);
250
251 env.vulkan_functions.vkDestroySurfaceKHR(inst, surface, nullptr);
252 }
253
254 // When ICD does support the surface creation, the loader should delegat handle it to the ICD
TEST(WsiTests,CreateSurfaceXCBICDSupport)255 TEST(WsiTests, CreateSurfaceXCBICDSupport) {
256 FrameworkEnvironment env{};
257 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
258 auto& cur_icd = env.get_test_icd(0);
259 cur_icd.set_min_icd_interface_version(5);
260 cur_icd.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME});
261 cur_icd.add_instance_extension({VK_KHR_XCB_SURFACE_EXTENSION_NAME});
262 cur_icd.enable_icd_wsi = true;
263
264 InstWrapper inst{env.vulkan_functions};
265 inst.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_XCB_SURFACE_EXTENSION_NAME});
266 inst.CheckCreate();
267
268 VkXcbSurfaceCreateInfoKHR xcb_createInfo{VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR};
269
270 VkSurfaceKHR surface{VK_NULL_HANDLE};
271 ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateXcbSurfaceKHR(inst, &xcb_createInfo, nullptr, &surface));
272 ASSERT_TRUE(surface != VK_NULL_HANDLE);
273
274 env.vulkan_functions.vkDestroySurfaceKHR(inst, surface, nullptr);
275 }
276
277 // Some drivers supporting vkCreateXcbSurfaceKHR, and at least one that doesn't
TEST(WsiTests,CreateSurfaceXCBMixedICDSupport)278 TEST(WsiTests, CreateSurfaceXCBMixedICDSupport) {
279 FrameworkEnvironment env{};
280 for (uint32_t icd = 0; icd < 3; ++icd) {
281 Extension first_ext{VK_KHR_SURFACE_EXTENSION_NAME};
282 Extension second_ext{VK_KHR_XCB_SURFACE_EXTENSION_NAME};
283 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
284 auto& cur_icd = env.get_test_icd(icd);
285 cur_icd.icd_api_version = VK_API_VERSION_1_0;
286 cur_icd.add_instance_extensions({first_ext, second_ext});
287 if (icd < 2) {
288 // Only enable ICD for first two
289 cur_icd.enable_icd_wsi = true;
290 }
291 }
292
293 InstWrapper instance(env.vulkan_functions);
294 instance.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_XCB_SURFACE_EXTENSION_NAME});
295 instance.CheckCreate();
296
297 VkXcbSurfaceCreateInfoKHR xcb_createInfo{VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR};
298
299 VkSurfaceKHR surface{VK_NULL_HANDLE};
300 ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateXcbSurfaceKHR(instance.inst, &xcb_createInfo, nullptr, &surface));
301 ASSERT_TRUE(surface != VK_NULL_HANDLE);
302
303 env.vulkan_functions.vkDestroySurfaceKHR(instance.inst, surface, nullptr);
304 }
305
TEST(WsiTests,GetPhysicalDeviceXcbPresentNoICDSupport)306 TEST(WsiTests, GetPhysicalDeviceXcbPresentNoICDSupport) {
307 FrameworkEnvironment env{};
308 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
309 auto& cur_icd = env.get_test_icd(0);
310 cur_icd.set_min_icd_interface_version(5);
311 cur_icd.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME});
312 cur_icd.add_instance_extension({VK_KHR_XCB_SURFACE_EXTENSION_NAME});
313 cur_icd.physical_devices.emplace_back("physical_device_0");
314 cur_icd.enable_icd_wsi = false;
315
316 InstWrapper inst{env.vulkan_functions};
317 inst.create_info.add_extensions(
318 {VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_XCB_SURFACE_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_EXTENSION_NAME});
319 inst.CheckCreate();
320
321 uint32_t driver_count = 1;
322 VkPhysicalDevice physical_device;
323 ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &driver_count, &physical_device));
324 ASSERT_EQ(driver_count, 1U);
325
326 DebugUtilsWrapper log{inst};
327 CreateDebugUtilsMessenger(log);
328 auto res = env.vulkan_functions.vkGetPhysicalDeviceXcbPresentationSupportKHR(physical_device, 0, nullptr, 0);
329 ASSERT_EQ(res, VK_FALSE);
330 ASSERT_TRUE(log.find("ICD for selected physical device does not export vkGetPhysicalDeviceXcbPresentationSupportKHR!"));
331 }
332
TEST(WsiTests,GetPhysicalDeviceXcbPresentICDSupport)333 TEST(WsiTests, GetPhysicalDeviceXcbPresentICDSupport) {
334 FrameworkEnvironment env{};
335 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
336 auto& cur_icd = env.get_test_icd(0);
337 cur_icd.set_min_icd_interface_version(5);
338 cur_icd.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME});
339 cur_icd.add_instance_extension({VK_KHR_XCB_SURFACE_EXTENSION_NAME});
340 cur_icd.physical_devices.emplace_back("physical_device_0");
341 cur_icd.enable_icd_wsi = true;
342
343 InstWrapper inst{env.vulkan_functions};
344 inst.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_XCB_SURFACE_EXTENSION_NAME});
345 inst.CheckCreate();
346
347 uint32_t driver_count = 1;
348 VkPhysicalDevice physical_device;
349 ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &driver_count, &physical_device));
350 ASSERT_EQ(driver_count, 1U);
351
352 ASSERT_EQ(VK_TRUE, env.vulkan_functions.vkGetPhysicalDeviceXcbPresentationSupportKHR(physical_device, 0, nullptr, 0));
353 }
354
TEST(WsiTests,XcbGetPhysicalDeviceSurfaceSupportKHR)355 TEST(WsiTests, XcbGetPhysicalDeviceSurfaceSupportKHR) {
356 FrameworkEnvironment env{};
357 const uint32_t max_device_count = 4;
358 for (uint32_t icd = 0; icd < max_device_count; ++icd) {
359 Extension first_ext{VK_KHR_SURFACE_EXTENSION_NAME};
360 Extension second_ext{VK_KHR_XCB_SURFACE_EXTENSION_NAME};
361 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
362 auto& cur_icd = env.get_test_icd(icd);
363 cur_icd.icd_api_version = VK_API_VERSION_1_0;
364 cur_icd.set_min_icd_interface_version(5);
365 cur_icd.add_instance_extensions({first_ext, second_ext});
366 std::string dev_name = "phys_dev_" + std::to_string(icd);
367 cur_icd.physical_devices.emplace_back(dev_name.c_str());
368 cur_icd.physical_devices.back().add_queue_family_properties({{VK_QUEUE_GRAPHICS_BIT, 1, 0, {1, 1, 1}}, true});
369 cur_icd.enable_icd_wsi = true;
370 }
371
372 InstWrapper instance(env.vulkan_functions);
373 instance.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_XCB_SURFACE_EXTENSION_NAME});
374 instance.CheckCreate();
375
376 VkSurfaceKHR surface{VK_NULL_HANDLE};
377 VkXcbSurfaceCreateInfoKHR xcb_createInfo{VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR};
378 ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateXcbSurfaceKHR(instance.inst, &xcb_createInfo, nullptr, &surface));
379 ASSERT_TRUE(surface != VK_NULL_HANDLE);
380
381 uint32_t device_count = max_device_count;
382 std::array<VkPhysicalDevice, max_device_count> phys_devs;
383 ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumeratePhysicalDevices(instance.inst, &device_count, phys_devs.data()));
384 ASSERT_EQ(device_count, max_device_count);
385
386 for (uint32_t pd = 0; pd < max_device_count; ++pd) {
387 VkBool32 supported = VK_FALSE;
388 ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkGetPhysicalDeviceSurfaceSupportKHR(phys_devs[pd], 0, surface, &supported));
389 }
390
391 env.vulkan_functions.vkDestroySurfaceKHR(instance.inst, surface, nullptr);
392 }
393 #endif
394
395 #if defined(VK_USE_PLATFORM_XLIB_KHR)
396 // When ICD doesn't support the extension, create instance should fail
TEST(WsiTests,CreateSurfaceXLIBNoICDSupport)397 TEST(WsiTests, CreateSurfaceXLIBNoICDSupport) {
398 FrameworkEnvironment env{};
399 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
400 auto& cur_icd = env.get_test_icd(0);
401 cur_icd.set_min_icd_interface_version(5);
402 cur_icd.enable_icd_wsi = false;
403
404 InstWrapper inst{env.vulkan_functions};
405 inst.create_info.add_extensions({VK_KHR_XLIB_SURFACE_EXTENSION_NAME});
406 inst.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
407
408 InstWrapper inst2{env.vulkan_functions};
409 inst2.CheckCreate();
410
411 ASSERT_EQ(nullptr, env.vulkan_functions.vkGetInstanceProcAddr(inst2.inst, "vkCreateXlibSurfaceKHR"));
412 }
413
414 // When ICD doesn't support the surface creation, the loader should handle it
TEST(WsiTests,CreateSurfaceXLIBNoICDCreateSupport)415 TEST(WsiTests, CreateSurfaceXLIBNoICDCreateSupport) {
416 FrameworkEnvironment env{};
417 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
418 auto& cur_icd = env.get_test_icd(0);
419 cur_icd.set_min_icd_interface_version(5);
420 cur_icd.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME});
421 cur_icd.add_instance_extension({VK_KHR_XLIB_SURFACE_EXTENSION_NAME});
422 cur_icd.enable_icd_wsi = false;
423
424 InstWrapper inst{env.vulkan_functions};
425 inst.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_XLIB_SURFACE_EXTENSION_NAME});
426 inst.CheckCreate();
427
428 VkXlibSurfaceCreateInfoKHR createInfo{VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR};
429
430 VkSurfaceKHR surface;
431 ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateXlibSurfaceKHR(inst, &createInfo, nullptr, &surface));
432 ASSERT_TRUE(surface != VK_NULL_HANDLE);
433
434 env.vulkan_functions.vkDestroySurfaceKHR(inst, surface, nullptr);
435 }
436
437 // When ICD does support the surface creation, the loader should delegat handle it to the ICD
TEST(WsiTests,CreateSurfaceXLIBICDSupport)438 TEST(WsiTests, CreateSurfaceXLIBICDSupport) {
439 FrameworkEnvironment env{};
440 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
441 auto& cur_icd = env.get_test_icd(0);
442 cur_icd.set_min_icd_interface_version(5);
443 cur_icd.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME});
444 cur_icd.add_instance_extension({VK_KHR_XLIB_SURFACE_EXTENSION_NAME});
445 cur_icd.enable_icd_wsi = true;
446
447 InstWrapper inst{env.vulkan_functions};
448 inst.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_XLIB_SURFACE_EXTENSION_NAME});
449 inst.CheckCreate();
450
451 VkXlibSurfaceCreateInfoKHR createInfo{VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR};
452
453 VkSurfaceKHR surface;
454 ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateXlibSurfaceKHR(inst, &createInfo, nullptr, &surface));
455 ASSERT_TRUE(surface != VK_NULL_HANDLE);
456
457 env.vulkan_functions.vkDestroySurfaceKHR(inst, surface, nullptr);
458 }
459
460 // Some drivers supporting vkCreateXlibSurfaceKHR, and at least one that doesn't
TEST(WsiTests,CreateSurfaceXLIBMixedICDSupport)461 TEST(WsiTests, CreateSurfaceXLIBMixedICDSupport) {
462 FrameworkEnvironment env{};
463 for (uint32_t icd = 0; icd < 3; ++icd) {
464 Extension first_ext{VK_KHR_SURFACE_EXTENSION_NAME};
465 Extension second_ext{VK_KHR_XLIB_SURFACE_EXTENSION_NAME};
466 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
467 auto& cur_icd = env.get_test_icd(icd);
468 cur_icd.icd_api_version = VK_API_VERSION_1_0;
469 cur_icd.add_instance_extensions({first_ext, second_ext});
470 if (icd < 2) {
471 // Only enable ICD for first two
472 cur_icd.enable_icd_wsi = true;
473 }
474 }
475
476 InstWrapper instance(env.vulkan_functions);
477 instance.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_XLIB_SURFACE_EXTENSION_NAME});
478 instance.CheckCreate();
479
480 VkXlibSurfaceCreateInfoKHR createInfo{VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR};
481
482 VkSurfaceKHR surface;
483 ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateXlibSurfaceKHR(instance.inst, &createInfo, nullptr, &surface));
484 ASSERT_TRUE(surface != VK_NULL_HANDLE);
485
486 env.vulkan_functions.vkDestroySurfaceKHR(instance.inst, surface, nullptr);
487 }
488
TEST(WsiTests,GetPhysicalDeviceXlibPresentNoICDSupport)489 TEST(WsiTests, GetPhysicalDeviceXlibPresentNoICDSupport) {
490 FrameworkEnvironment env{};
491 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
492 auto& cur_icd = env.get_test_icd(0);
493 cur_icd.set_min_icd_interface_version(5);
494 cur_icd.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME});
495 cur_icd.add_instance_extension({VK_KHR_XLIB_SURFACE_EXTENSION_NAME});
496 cur_icd.physical_devices.emplace_back("physical_device_0");
497 cur_icd.enable_icd_wsi = false;
498
499 InstWrapper inst{env.vulkan_functions};
500 inst.create_info.add_extensions(
501 {VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_XLIB_SURFACE_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_EXTENSION_NAME});
502 inst.CheckCreate();
503
504 uint32_t driver_count = 1;
505 VkPhysicalDevice physical_device;
506 ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &driver_count, &physical_device));
507 ASSERT_EQ(driver_count, 1U);
508
509 DebugUtilsWrapper log{inst};
510 CreateDebugUtilsMessenger(log);
511 auto res = env.vulkan_functions.vkGetPhysicalDeviceXlibPresentationSupportKHR(physical_device, 0, nullptr, 0);
512 ASSERT_EQ(res, VK_FALSE);
513 ASSERT_TRUE(log.find("ICD for selected physical device does not export vkGetPhysicalDeviceXlibPresentationSupportKHR!"));
514 }
515
TEST(WsiTests,GetPhysicalDeviceXlibPresentICDSupport)516 TEST(WsiTests, GetPhysicalDeviceXlibPresentICDSupport) {
517 FrameworkEnvironment env{};
518 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
519 auto& cur_icd = env.get_test_icd(0);
520 cur_icd.set_min_icd_interface_version(5);
521 cur_icd.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME});
522 cur_icd.add_instance_extension({VK_KHR_XLIB_SURFACE_EXTENSION_NAME});
523 cur_icd.physical_devices.emplace_back("physical_device_0");
524 cur_icd.enable_icd_wsi = true;
525
526 InstWrapper inst{env.vulkan_functions};
527 inst.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_XLIB_SURFACE_EXTENSION_NAME});
528 inst.CheckCreate();
529
530 uint32_t driver_count = 1;
531 VkPhysicalDevice physical_device;
532 ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &driver_count, &physical_device));
533 ASSERT_EQ(driver_count, 1U);
534
535 ASSERT_EQ(VK_TRUE, env.vulkan_functions.vkGetPhysicalDeviceXlibPresentationSupportKHR(physical_device, 0, nullptr, 0));
536 }
537
TEST(WsiTests,XlibGetPhysicalDeviceSurfaceSupportKHR)538 TEST(WsiTests, XlibGetPhysicalDeviceSurfaceSupportKHR) {
539 FrameworkEnvironment env{};
540 const uint32_t max_device_count = 4;
541 for (uint32_t icd = 0; icd < max_device_count; ++icd) {
542 Extension first_ext{VK_KHR_SURFACE_EXTENSION_NAME};
543 Extension second_ext{VK_KHR_XLIB_SURFACE_EXTENSION_NAME};
544 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
545 auto& cur_icd = env.get_test_icd(icd);
546 cur_icd.icd_api_version = VK_API_VERSION_1_0;
547 cur_icd.set_min_icd_interface_version(5);
548 cur_icd.add_instance_extensions({first_ext, second_ext});
549 std::string dev_name = "phys_dev_" + std::to_string(icd);
550 cur_icd.physical_devices.emplace_back(dev_name.c_str());
551 cur_icd.physical_devices.back().add_queue_family_properties({{VK_QUEUE_GRAPHICS_BIT, 1, 0, {1, 1, 1}}, true});
552 cur_icd.enable_icd_wsi = true;
553 }
554
555 InstWrapper instance(env.vulkan_functions);
556 instance.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_XLIB_SURFACE_EXTENSION_NAME});
557 instance.CheckCreate();
558
559 VkSurfaceKHR surface{VK_NULL_HANDLE};
560 VkXlibSurfaceCreateInfoKHR createInfo{VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR};
561 ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateXlibSurfaceKHR(instance.inst, &createInfo, nullptr, &surface));
562 ASSERT_TRUE(surface != VK_NULL_HANDLE);
563
564 uint32_t device_count = max_device_count;
565 std::array<VkPhysicalDevice, max_device_count> phys_devs;
566 ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumeratePhysicalDevices(instance.inst, &device_count, phys_devs.data()));
567 ASSERT_EQ(device_count, max_device_count);
568
569 for (uint32_t pd = 0; pd < max_device_count; ++pd) {
570 VkBool32 supported = VK_FALSE;
571 ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkGetPhysicalDeviceSurfaceSupportKHR(phys_devs[pd], 0, surface, &supported));
572 }
573
574 env.vulkan_functions.vkDestroySurfaceKHR(instance.inst, surface, nullptr);
575 }
576 #endif
577
578 #if defined(VK_USE_PLATFORM_WAYLAND_KHR)
579 // When ICD doesn't support the extension, create instance should fail
TEST(WsiTests,CreateSurfaceWaylandNoICDSupport)580 TEST(WsiTests, CreateSurfaceWaylandNoICDSupport) {
581 FrameworkEnvironment env{};
582 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
583 auto& cur_icd = env.get_test_icd(0);
584 cur_icd.set_min_icd_interface_version(5);
585 cur_icd.enable_icd_wsi = false;
586
587 InstWrapper inst{env.vulkan_functions};
588 inst.create_info.add_extensions({VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME});
589 inst.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
590
591 InstWrapper inst2{env.vulkan_functions};
592 inst2.CheckCreate();
593
594 ASSERT_EQ(nullptr, env.vulkan_functions.vkGetInstanceProcAddr(inst2.inst, "vkCreateWaylandSurfaceKHR"));
595 }
596
597 // When ICD doesn't support the surface creation, the loader should handle it
TEST(WsiTests,CreateSurfaceWaylandNoICDCreateSupport)598 TEST(WsiTests, CreateSurfaceWaylandNoICDCreateSupport) {
599 FrameworkEnvironment env{};
600 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
601 auto& cur_icd = env.get_test_icd(0);
602 cur_icd.set_min_icd_interface_version(5);
603 cur_icd.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME});
604 cur_icd.add_instance_extension({VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME});
605 cur_icd.enable_icd_wsi = false;
606
607 InstWrapper inst{env.vulkan_functions};
608 inst.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME});
609 inst.CheckCreate();
610
611 VkWaylandSurfaceCreateInfoKHR createInfo{VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR};
612
613 VkSurfaceKHR surface;
614 ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateWaylandSurfaceKHR(inst, &createInfo, nullptr, &surface));
615 ASSERT_TRUE(surface != VK_NULL_HANDLE);
616
617 env.vulkan_functions.vkDestroySurfaceKHR(inst, surface, nullptr);
618 }
619
620 // When ICD does support the surface creation, the loader should delegat handle it to the ICD
TEST(WsiTests,CreateSurfaceWaylandICDSupport)621 TEST(WsiTests, CreateSurfaceWaylandICDSupport) {
622 FrameworkEnvironment env{};
623 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
624 auto& cur_icd = env.get_test_icd(0);
625 cur_icd.set_min_icd_interface_version(5);
626 cur_icd.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME});
627 cur_icd.add_instance_extension({VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME});
628 cur_icd.enable_icd_wsi = true;
629
630 InstWrapper inst{env.vulkan_functions};
631 inst.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME});
632 inst.CheckCreate();
633
634 VkWaylandSurfaceCreateInfoKHR createInfo{VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR};
635
636 VkSurfaceKHR surface;
637 ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateWaylandSurfaceKHR(inst, &createInfo, nullptr, &surface));
638 ASSERT_TRUE(surface != VK_NULL_HANDLE);
639
640 env.vulkan_functions.vkDestroySurfaceKHR(inst, surface, nullptr);
641 }
642
643 // Some drivers supporting vkCreateWaylandSurfaceKHR, and at least one that doesn't
TEST(WsiTests,CreateSurfaceWaylandMixedICDSupport)644 TEST(WsiTests, CreateSurfaceWaylandMixedICDSupport) {
645 FrameworkEnvironment env{};
646 for (uint32_t icd = 0; icd < 3; ++icd) {
647 Extension first_ext{VK_KHR_SURFACE_EXTENSION_NAME};
648 Extension second_ext{VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME};
649 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
650 auto& cur_icd = env.get_test_icd(icd);
651 cur_icd.icd_api_version = VK_API_VERSION_1_0;
652 cur_icd.add_instance_extensions({first_ext, second_ext});
653 if (icd < 2) {
654 // Only enable ICD for first two
655 cur_icd.enable_icd_wsi = true;
656 }
657 }
658
659 InstWrapper instance(env.vulkan_functions);
660 instance.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME});
661 instance.CheckCreate();
662
663 VkWaylandSurfaceCreateInfoKHR createInfo{VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR};
664
665 VkSurfaceKHR surface;
666 ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateWaylandSurfaceKHR(instance.inst, &createInfo, nullptr, &surface));
667 ASSERT_TRUE(surface != VK_NULL_HANDLE);
668
669 env.vulkan_functions.vkDestroySurfaceKHR(instance.inst, surface, nullptr);
670 }
671
TEST(WsiTests,GetPhysicalDeviceWaylandPresentNoICDSupport)672 TEST(WsiTests, GetPhysicalDeviceWaylandPresentNoICDSupport) {
673 FrameworkEnvironment env{};
674 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
675 auto& cur_icd = env.get_test_icd(0);
676 cur_icd.set_min_icd_interface_version(5);
677 cur_icd.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME});
678 cur_icd.add_instance_extension({VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME});
679 cur_icd.physical_devices.emplace_back("physical_device_0");
680 cur_icd.enable_icd_wsi = false;
681
682 InstWrapper inst{env.vulkan_functions};
683 inst.create_info.add_extensions(
684 {VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_EXTENSION_NAME});
685 inst.CheckCreate();
686
687 uint32_t driver_count = 1;
688 VkPhysicalDevice physical_device;
689 ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &driver_count, &physical_device));
690 ASSERT_EQ(driver_count, 1U);
691
692 DebugUtilsWrapper log{inst};
693 CreateDebugUtilsMessenger(log);
694 auto res = env.vulkan_functions.vkGetPhysicalDeviceWaylandPresentationSupportKHR(physical_device, 0, nullptr);
695 ASSERT_EQ(res, VK_FALSE);
696 ASSERT_TRUE(log.find("ICD for selected physical device does not export vkGetPhysicalDeviceWaylandPresentationSupportKHR!"));
697 }
698
TEST(WsiTests,GetPhysicalDeviceWaylandPresentICDSupport)699 TEST(WsiTests, GetPhysicalDeviceWaylandPresentICDSupport) {
700 FrameworkEnvironment env{};
701 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
702 auto& cur_icd = env.get_test_icd(0);
703 cur_icd.set_min_icd_interface_version(5);
704 cur_icd.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME});
705 cur_icd.add_instance_extension({VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME});
706 cur_icd.physical_devices.emplace_back("physical_device_0");
707 cur_icd.enable_icd_wsi = true;
708
709 InstWrapper inst{env.vulkan_functions};
710 inst.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME});
711 inst.CheckCreate();
712
713 uint32_t driver_count = 1;
714 VkPhysicalDevice physical_device;
715 ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &driver_count, &physical_device));
716 ASSERT_EQ(driver_count, 1U);
717
718 ASSERT_EQ(VK_TRUE, env.vulkan_functions.vkGetPhysicalDeviceWaylandPresentationSupportKHR(physical_device, 0, nullptr));
719 }
720
TEST(WsiTests,WaylandGetPhysicalDeviceSurfaceSupportKHR)721 TEST(WsiTests, WaylandGetPhysicalDeviceSurfaceSupportKHR) {
722 FrameworkEnvironment env{};
723 const uint32_t max_device_count = 4;
724 for (uint32_t icd = 0; icd < max_device_count; ++icd) {
725 Extension first_ext{VK_KHR_SURFACE_EXTENSION_NAME};
726 Extension second_ext{VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME};
727 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
728 auto& cur_icd = env.get_test_icd(icd);
729 cur_icd.icd_api_version = VK_API_VERSION_1_0;
730 cur_icd.set_min_icd_interface_version(5);
731 cur_icd.add_instance_extensions({first_ext, second_ext});
732 std::string dev_name = "phys_dev_" + std::to_string(icd);
733 cur_icd.physical_devices.emplace_back(dev_name.c_str());
734 cur_icd.physical_devices.back().add_queue_family_properties({{VK_QUEUE_GRAPHICS_BIT, 1, 0, {1, 1, 1}}, true});
735 cur_icd.enable_icd_wsi = true;
736 }
737
738 InstWrapper instance(env.vulkan_functions);
739 instance.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME});
740 instance.CheckCreate();
741
742 VkSurfaceKHR surface{VK_NULL_HANDLE};
743 VkWaylandSurfaceCreateInfoKHR createInfo{VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR};
744 ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateWaylandSurfaceKHR(instance.inst, &createInfo, nullptr, &surface));
745 ASSERT_TRUE(surface != VK_NULL_HANDLE);
746
747 uint32_t device_count = max_device_count;
748 std::array<VkPhysicalDevice, max_device_count> phys_devs;
749 ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumeratePhysicalDevices(instance.inst, &device_count, phys_devs.data()));
750 ASSERT_EQ(device_count, max_device_count);
751
752 for (uint32_t pd = 0; pd < max_device_count; ++pd) {
753 VkBool32 supported = VK_FALSE;
754 ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkGetPhysicalDeviceSurfaceSupportKHR(phys_devs[pd], 0, surface, &supported));
755 }
756
757 env.vulkan_functions.vkDestroySurfaceKHR(instance.inst, surface, nullptr);
758 }
759 #endif
760
TEST(WsiTests,GoogleSurfaceslessQuery)761 TEST(WsiTests, GoogleSurfaceslessQuery) {
762 std::vector<VkPresentModeKHR> present_modes{VK_PRESENT_MODE_FIFO_KHR, VK_PRESENT_MODE_IMMEDIATE_KHR,
763 VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_FIFO_RELAXED_KHR};
764 VkSurfaceFormatKHR surface_format = {VK_FORMAT_R8G8B8A8_SRGB, VK_COLORSPACE_SRGB_NONLINEAR_KHR};
765 FrameworkEnvironment env{};
766 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2))
767 .setup_WSI()
768 .add_instance_extension("VK_GOOGLE_surfaceless_query")
769 .add_instance_extension("VK_KHR_get_surface_capabilities2")
770 .add_physical_device(PhysicalDevice{}
771 .add_extension("VK_KHR_swapchain")
772 #if defined(WIN32)
773 .add_extension("VK_EXT_full_screen_exclusive")
774 #endif
775 .add_surface_format(surface_format)
776 .add_surface_present_modes(present_modes)
777 .finish());
778
779 InstWrapper inst{env.vulkan_functions};
780 inst.create_info.add_extension("VK_KHR_surface");
781 inst.create_info.add_extension("VK_GOOGLE_surfaceless_query");
782 ASSERT_NO_FATAL_FAILURE(inst.CheckCreate());
783
784 VkPhysicalDevice physical_device = inst.GetPhysDev();
785
786 uint32_t present_mode_count = 4;
787 std::vector<VkPresentModeKHR> queried_present_modes{present_mode_count};
788 inst->vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, VK_NULL_HANDLE, &present_mode_count,
789 queried_present_modes.data());
790 ASSERT_EQ(present_modes, queried_present_modes);
791
792 uint32_t surface_format_count = 1;
793 std::vector<VkSurfaceFormatKHR> queried_surface_formats{surface_format_count};
794 inst->vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, VK_NULL_HANDLE, &surface_format_count,
795 queried_surface_formats.data());
796 ASSERT_EQ(std::vector<VkSurfaceFormatKHR>{surface_format}, queried_surface_formats);
797
798 uint32_t surface_format2_count = 1;
799 std::vector<VkSurfaceFormat2KHR> queried_surface_formats2{surface_format2_count};
800 VkPhysicalDeviceSurfaceInfo2KHR surface_info{};
801 surface_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR;
802 surface_info.surface = VK_NULL_HANDLE;
803 inst->vkGetPhysicalDeviceSurfaceFormats2KHR(physical_device, &surface_info, &surface_format_count,
804 queried_surface_formats2.data());
805 ASSERT_EQ(std::vector<VkSurfaceFormatKHR>{surface_format}, queried_surface_formats2);
806
807 VkSurfaceCapabilities2KHR surface_caps2{};
808 surface_caps2.sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR;
809
810 ASSERT_EQ(VK_SUCCESS,
811 env.vulkan_functions.vkGetPhysicalDeviceSurfaceCapabilities2KHR(physical_device, &surface_info, &surface_caps2));
812
813 #if defined(WIN32)
814 PFN_vkGetPhysicalDeviceSurfacePresentModes2EXT pfn_vkGetPhysicalDeviceSurfacePresentModes2EXT =
815 inst.load("vkGetPhysicalDeviceSurfacePresentModes2EXT");
816 ASSERT_EQ(VK_SUCCESS, pfn_vkGetPhysicalDeviceSurfacePresentModes2EXT(physical_device, &surface_info, &present_mode_count,
817 queried_present_modes.data()));
818 ASSERT_EQ(present_modes, queried_present_modes);
819
820 #endif
821 }
822
TEST(WsiTests,ForgetEnableSurfaceExtensions)823 TEST(WsiTests, ForgetEnableSurfaceExtensions) {
824 FrameworkEnvironment env{};
825 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2))
826 .setup_WSI()
827 .add_physical_device(PhysicalDevice{}.add_extension("VK_KHR_swapchain").finish());
828
829 InstWrapper inst{env.vulkan_functions};
830 inst.create_info.add_extension("VK_KHR_surface");
831 ASSERT_NO_FATAL_FAILURE(inst.CheckCreate());
832
833 VkSurfaceKHR surface{};
834 ASSERT_EQ(VK_ERROR_EXTENSION_NOT_PRESENT, create_surface(inst, surface));
835 }
836
TEST(WsiTests,SwapchainFunctional)837 TEST(WsiTests, SwapchainFunctional) {
838 FrameworkEnvironment env{};
839 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2))
840 .setup_WSI()
841 .add_physical_device(PhysicalDevice{}.add_extension("VK_KHR_swapchain").finish());
842
843 InstWrapper inst{env.vulkan_functions};
844 inst.create_info.setup_WSI();
845 inst.CheckCreate();
846 VkSurfaceKHR surface{};
847 ASSERT_EQ(VK_SUCCESS, create_surface(inst, surface));
848 VkPhysicalDevice phys_dev = inst.GetPhysDev();
849
850 { // Use GDPA to get functions
851 DeviceWrapper dev{inst};
852 dev.create_info.add_extension("VK_KHR_swapchain");
853
854 ASSERT_NO_FATAL_FAILURE(dev.CheckCreate(phys_dev));
855
856 VkSwapchainKHR swapchain{};
857 VkSwapchainCreateInfoKHR swap_create_info{};
858 swap_create_info.surface = surface;
859 DeviceFunctions funcs{*inst.functions, dev};
860 ASSERT_EQ(VK_SUCCESS, funcs.vkCreateSwapchainKHR(dev, &swap_create_info, nullptr, &swapchain));
861 uint32_t count = 0;
862 ASSERT_EQ(VK_SUCCESS, funcs.vkGetSwapchainImagesKHR(dev, swapchain, &count, nullptr));
863 ASSERT_GT(count, 0U);
864 std::array<VkImage, 16> images;
865 ASSERT_EQ(VK_SUCCESS, funcs.vkGetSwapchainImagesKHR(dev, swapchain, &count, images.data()));
866 funcs.vkDestroySwapchainKHR(dev, swapchain, nullptr);
867 }
868 { // Use GIPA gotten functions
869 DeviceWrapper dev{inst};
870 dev.create_info.add_extension("VK_KHR_swapchain");
871
872 ASSERT_NO_FATAL_FAILURE(dev.CheckCreate(phys_dev));
873
874 PFN_vkCreateSwapchainKHR inst_CreateSwapchainKHR = inst.load("vkCreateSwapchainKHR");
875 PFN_vkGetSwapchainImagesKHR inst_GetSwapchainImagesKHR = inst.load("vkGetSwapchainImagesKHR");
876 PFN_vkDestroySwapchainKHR inst_DestroySwapchainKHR = inst.load("vkDestroySwapchainKHR");
877 ASSERT_TRUE(nullptr != inst_CreateSwapchainKHR);
878 ASSERT_TRUE(nullptr != inst_GetSwapchainImagesKHR);
879 ASSERT_TRUE(nullptr != inst_DestroySwapchainKHR);
880
881 VkSwapchainKHR swapchain{};
882 VkSwapchainCreateInfoKHR swap_create_info{};
883 swap_create_info.surface = surface;
884
885 ASSERT_EQ(VK_SUCCESS, inst_CreateSwapchainKHR(dev, &swap_create_info, nullptr, &swapchain));
886 uint32_t count = 0;
887 ASSERT_EQ(VK_SUCCESS, inst_GetSwapchainImagesKHR(dev, swapchain, &count, nullptr));
888 ASSERT_GT(count, 0U);
889 std::array<VkImage, 16> images;
890 ASSERT_EQ(VK_SUCCESS, inst_GetSwapchainImagesKHR(dev, swapchain, &count, images.data()));
891 inst_DestroySwapchainKHR(dev, swapchain, nullptr);
892 }
893 { // forget to enable the extension
894 DeviceWrapper dev{inst};
895 ASSERT_NO_FATAL_FAILURE(dev.CheckCreate(phys_dev));
896
897 DeviceFunctions funcs{*inst.functions, dev};
898 ASSERT_EQ(funcs.vkCreateSwapchainKHR, nullptr);
899 ASSERT_EQ(funcs.vkGetSwapchainImagesKHR, nullptr);
900 ASSERT_EQ(funcs.vkDestroySwapchainKHR, nullptr);
901 }
902 { // forget to set the surface
903 DeviceWrapper dev{inst};
904 dev.create_info.add_extension("VK_KHR_swapchain");
905
906 dev.CheckCreate(phys_dev);
907
908 VkSwapchainKHR swapchain{};
909 VkSwapchainCreateInfoKHR swap_create_info{};
910 DeviceFunctions funcs{*inst.functions, dev};
911 ASSERT_DEATH(funcs.vkCreateSwapchainKHR(dev, &swap_create_info, nullptr, &swapchain), "");
912 }
913 env.vulkan_functions.vkDestroySurfaceKHR(inst.inst, surface, nullptr);
914 }
915
TEST(WsiTests,EXTSurfaceMaintenance1)916 TEST(WsiTests, EXTSurfaceMaintenance1) {
917 FrameworkEnvironment env{};
918
919 std::vector<VkPresentModeKHR> present_modes{VK_PRESENT_MODE_FIFO_KHR, VK_PRESENT_MODE_IMMEDIATE_KHR,
920 VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_FIFO_RELAXED_KHR};
921 VkSurfaceCapabilitiesKHR surface_caps{};
922 surface_caps.maxImageExtent = VkExtent2D{300, 300};
923 surface_caps.minImageExtent = VkExtent2D{100, 100};
924 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2))
925 .setup_WSI()
926 .add_instance_extension(VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME)
927 .add_physical_device(PhysicalDevice{}
928 .add_extension("VK_KHR_swapchain")
929 .set_deviceName("no")
930 .set_surface_capabilities(surface_caps)
931 .add_surface_present_modes(present_modes)
932 .finish());
933 VkSurfacePresentScalingCapabilitiesEXT scaling_capabilities{};
934 scaling_capabilities.supportedPresentScaling = VK_PRESENT_SCALING_ONE_TO_ONE_BIT_EXT;
935 scaling_capabilities.supportedPresentGravityX = VK_PRESENT_SCALING_ASPECT_RATIO_STRETCH_BIT_EXT;
936 scaling_capabilities.supportedPresentGravityY = VK_PRESENT_SCALING_STRETCH_BIT_EXT;
937 scaling_capabilities.minScaledImageExtent = {60, 60};
938 scaling_capabilities.maxScaledImageExtent = {1000, 1000};
939 auto& icd2 = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2))
940 .setup_WSI()
941 .add_instance_extension(VK_EXT_SURFACE_MAINTENANCE_1_EXTENSION_NAME)
942 .add_instance_extension(VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME)
943 .add_physical_device(PhysicalDevice{}
944 .add_extension("VK_KHR_swapchain")
945 .set_deviceName("yes")
946 .set_surface_capabilities(surface_caps)
947 .add_surface_present_modes(present_modes)
948 .set_surface_present_scaling_capabilities(scaling_capabilities)
949 .finish());
950 std::vector<std::vector<VkPresentModeKHR>> compatible_present_modes{
951 {VK_PRESENT_MODE_FIFO_KHR, VK_PRESENT_MODE_FIFO_RELAXED_KHR},
952 {VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_MAILBOX_KHR},
953 {VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_IMMEDIATE_KHR},
954 {VK_PRESENT_MODE_FIFO_RELAXED_KHR, VK_PRESENT_MODE_FIFO_KHR},
955 };
956 icd2.physical_devices[0].surface_present_mode_compatibility = compatible_present_modes;
957 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2))
958 .setup_WSI()
959 .add_physical_device(PhysicalDevice{}
960 .add_extension("VK_KHR_swapchain")
961 .set_deviceName("no")
962 .set_surface_capabilities(surface_caps)
963 .add_surface_present_modes(present_modes)
964 .finish());
965
966 InstWrapper inst{env.vulkan_functions};
967 inst.create_info.setup_WSI();
968 inst.create_info.add_extension(VK_EXT_SURFACE_MAINTENANCE_1_EXTENSION_NAME);
969 inst.create_info.add_extension(VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME);
970 inst.CheckCreate();
971
972 VkSurfaceKHR surface{};
973 ASSERT_EQ(VK_SUCCESS, create_surface(inst, surface));
974 WrappedHandle<VkSurfaceKHR, VkInstance, PFN_vkDestroySurfaceKHR> wrapped_surface{surface, inst.inst,
975 env.vulkan_functions.vkDestroySurfaceKHR};
976 auto physical_devices = inst.GetPhysDevs(3);
977
978 for (auto physical_device : physical_devices) {
979 VkPhysicalDeviceProperties phys_dev_props{};
980 inst->vkGetPhysicalDeviceProperties(physical_device, &phys_dev_props);
981 bool driver_support_surface_maintenance1 = string_eq(phys_dev_props.deviceName, "yes");
982
983 uint32_t present_mode_count = 4;
984 std::vector<VkPresentModeKHR> queried_present_modes{present_mode_count};
985 inst->vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &present_mode_count,
986 queried_present_modes.data());
987
988 for (uint32_t i = 0; i < present_mode_count; i++) {
989 VkSurfacePresentModeEXT present_mode{};
990 present_mode.sType = VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_EXT;
991 present_mode.presentMode = queried_present_modes[i];
992
993 VkPhysicalDeviceSurfaceInfo2KHR surface_info{};
994 surface_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR;
995 surface_info.surface = surface;
996 surface_info.pNext = &present_mode;
997
998 VkSurfacePresentModeCompatibilityEXT SurfacePresentModeCompatibilityEXT{};
999 SurfacePresentModeCompatibilityEXT.sType = VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_COMPATIBILITY_EXT;
1000
1001 VkSurfacePresentScalingCapabilitiesEXT SurfacePresentScalingCapabilitiesEXT{};
1002 SurfacePresentScalingCapabilitiesEXT.sType = VK_STRUCTURE_TYPE_SURFACE_PRESENT_SCALING_CAPABILITIES_EXT;
1003 SurfacePresentScalingCapabilitiesEXT.pNext = &SurfacePresentModeCompatibilityEXT;
1004
1005 VkSurfaceCapabilities2KHR surface_caps2{};
1006 surface_caps2.sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR;
1007 surface_caps2.pNext = &SurfacePresentScalingCapabilitiesEXT;
1008
1009 ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkGetPhysicalDeviceSurfaceCapabilities2KHR(physical_device, &surface_info,
1010 &surface_caps2));
1011 if (driver_support_surface_maintenance1) {
1012 ASSERT_EQ(SurfacePresentModeCompatibilityEXT.presentModeCount, 2U);
1013 } else {
1014 ASSERT_EQ(SurfacePresentModeCompatibilityEXT.presentModeCount, 1U);
1015 }
1016 std::vector<VkPresentModeKHR> queried_compatible_present_modes{SurfacePresentModeCompatibilityEXT.presentModeCount};
1017 SurfacePresentModeCompatibilityEXT.pPresentModes = queried_compatible_present_modes.data();
1018
1019 ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkGetPhysicalDeviceSurfaceCapabilities2KHR(physical_device, &surface_info,
1020 &surface_caps2));
1021
1022 if (driver_support_surface_maintenance1) {
1023 ASSERT_EQ(compatible_present_modes[i], queried_compatible_present_modes);
1024 ASSERT_EQ(scaling_capabilities, SurfacePresentScalingCapabilitiesEXT);
1025 } else {
1026 // Make sure the emulation returned the values we expect - 1 compatible present mode which is the mode we are
1027 // querying, Scaling capabilities is 0 (aka none) and the extent is just the surface caps extent
1028 ASSERT_EQ(SurfacePresentModeCompatibilityEXT.presentModeCount, 1U);
1029 ASSERT_EQ(SurfacePresentModeCompatibilityEXT.pPresentModes[0], queried_present_modes[i]);
1030 ASSERT_EQ(SurfacePresentScalingCapabilitiesEXT.supportedPresentScaling, 0U);
1031 ASSERT_EQ(SurfacePresentScalingCapabilitiesEXT.supportedPresentGravityX, 0u);
1032 ASSERT_EQ(SurfacePresentScalingCapabilitiesEXT.supportedPresentGravityY, 0U);
1033 ASSERT_EQ(SurfacePresentScalingCapabilitiesEXT.minScaledImageExtent, surface_caps.minImageExtent);
1034 ASSERT_EQ(SurfacePresentScalingCapabilitiesEXT.maxScaledImageExtent, surface_caps.maxImageExtent);
1035 }
1036 }
1037 }
1038 }
1039