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, ForgetEnableSurfaceExtensions)761 TEST(WsiTests, ForgetEnableSurfaceExtensions) {
762     FrameworkEnvironment env{};
763     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2))
764         .setup_WSI()
765         .add_physical_device(PhysicalDevice{}.add_extension("VK_KHR_swapchain").finish());
766 
767     InstWrapper inst{env.vulkan_functions};
768     inst.create_info.add_extension("VK_KHR_surface");
769     ASSERT_NO_FATAL_FAILURE(inst.CheckCreate());
770 
771     VkSurfaceKHR surface{};
772     ASSERT_EQ(VK_ERROR_EXTENSION_NOT_PRESENT, create_surface(inst, surface));
773 }
774 
TEST(WsiTests, SwapchainFunctional)775 TEST(WsiTests, SwapchainFunctional) {
776     FrameworkEnvironment env{};
777     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2))
778         .setup_WSI()
779         .add_physical_device(PhysicalDevice{}.add_extension("VK_KHR_swapchain").finish());
780 
781     InstWrapper inst{env.vulkan_functions};
782     inst.create_info.setup_WSI();
783     inst.CheckCreate();
784     VkSurfaceKHR surface{};
785     ASSERT_EQ(VK_SUCCESS, create_surface(inst, surface));
786     VkPhysicalDevice phys_dev = inst.GetPhysDev();
787 
788     {  // Use GDPA to get functions
789         DeviceWrapper dev{inst};
790         dev.create_info.add_extension("VK_KHR_swapchain");
791 
792         ASSERT_NO_FATAL_FAILURE(dev.CheckCreate(phys_dev));
793 
794         VkSwapchainKHR swapchain{};
795         VkSwapchainCreateInfoKHR swap_create_info{};
796         swap_create_info.surface = surface;
797         DeviceFunctions funcs{*inst.functions, dev};
798         ASSERT_EQ(VK_SUCCESS, funcs.vkCreateSwapchainKHR(dev, &swap_create_info, nullptr, &swapchain));
799         uint32_t count = 0;
800         ASSERT_EQ(VK_SUCCESS, funcs.vkGetSwapchainImagesKHR(dev, swapchain, &count, nullptr));
801         ASSERT_GT(count, 0U);
802         std::array<VkImage, 16> images;
803         ASSERT_EQ(VK_SUCCESS, funcs.vkGetSwapchainImagesKHR(dev, swapchain, &count, images.data()));
804         funcs.vkDestroySwapchainKHR(dev, swapchain, nullptr);
805     }
806     {  // Use GIPA gotten functions
807         DeviceWrapper dev{inst};
808         dev.create_info.add_extension("VK_KHR_swapchain");
809 
810         ASSERT_NO_FATAL_FAILURE(dev.CheckCreate(phys_dev));
811 
812         PFN_vkCreateSwapchainKHR inst_CreateSwapchainKHR = inst.load("vkCreateSwapchainKHR");
813         PFN_vkGetSwapchainImagesKHR inst_GetSwapchainImagesKHR = inst.load("vkGetSwapchainImagesKHR");
814         PFN_vkDestroySwapchainKHR inst_DestroySwapchainKHR = inst.load("vkDestroySwapchainKHR");
815         ASSERT_TRUE(nullptr != inst_CreateSwapchainKHR);
816         ASSERT_TRUE(nullptr != inst_GetSwapchainImagesKHR);
817         ASSERT_TRUE(nullptr != inst_DestroySwapchainKHR);
818 
819         VkSwapchainKHR swapchain{};
820         VkSwapchainCreateInfoKHR swap_create_info{};
821         swap_create_info.surface = surface;
822 
823         ASSERT_EQ(VK_SUCCESS, inst_CreateSwapchainKHR(dev, &swap_create_info, nullptr, &swapchain));
824         uint32_t count = 0;
825         ASSERT_EQ(VK_SUCCESS, inst_GetSwapchainImagesKHR(dev, swapchain, &count, nullptr));
826         ASSERT_GT(count, 0U);
827         std::array<VkImage, 16> images;
828         ASSERT_EQ(VK_SUCCESS, inst_GetSwapchainImagesKHR(dev, swapchain, &count, images.data()));
829         inst_DestroySwapchainKHR(dev, swapchain, nullptr);
830     }
831     {  // forget to enable the extension
832         DeviceWrapper dev{inst};
833         ASSERT_NO_FATAL_FAILURE(dev.CheckCreate(phys_dev));
834 
835         DeviceFunctions funcs{*inst.functions, dev};
836         ASSERT_EQ(funcs.vkCreateSwapchainKHR, nullptr);
837         ASSERT_EQ(funcs.vkGetSwapchainImagesKHR, nullptr);
838         ASSERT_EQ(funcs.vkDestroySwapchainKHR, nullptr);
839     }
840     {  // forget to set the surface
841         DeviceWrapper dev{inst};
842         dev.create_info.add_extension("VK_KHR_swapchain");
843 
844         dev.CheckCreate(phys_dev);
845 
846         VkSwapchainKHR swapchain{};
847         VkSwapchainCreateInfoKHR swap_create_info{};
848         DeviceFunctions funcs{*inst.functions, dev};
849         ASSERT_DEATH(funcs.vkCreateSwapchainKHR(dev, &swap_create_info, nullptr, &swapchain), "");
850     }
851     env.vulkan_functions.vkDestroySurfaceKHR(inst.inst, surface, nullptr);
852 }
853