• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 The Khronos Group Inc.
3  * Copyright (c) 2021-2022 Valve Corporation
4  * Copyright (c) 2021-2022 LunarG, Inc.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and/or associated documentation files (the "Materials"), to
8  * deal in the Materials without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Materials, and to permit persons to whom the Materials are
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice(s) and this permission notice shall be included in
14  * all copies or substantial portions of the Materials.
15  *
16  * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19  *
20  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
21  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
23  * USE OR OTHER DEALINGS IN THE MATERIALS.
24  *
25  * Author: Charles Giessen <charles@lunarg.com>
26  */
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