/* * Copyright (c) 2021-2022 The Khronos Group Inc. * Copyright (c) 2021-2022 Valve Corporation * Copyright (c) 2021-2022 LunarG, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and/or associated documentation files (the "Materials"), to * deal in the Materials without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Materials, and to permit persons to whom the Materials are * furnished to do so, subject to the following conditions: * * The above copyright notice(s) and this permission notice shall be included in * all copies or substantial portions of the Materials. * * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE * USE OR OTHER DEALINGS IN THE MATERIALS. * * Author: Charles Giessen */ #include "test_environment.h" class WsiTests : public ::testing::Test {}; #if defined(VK_USE_PLATFORM_WIN32_KHR) // When ICD doesn't support the extension, create instance should fail TEST(WsiTests, CreateSurfaceWin32NoICDSupport) { FrameworkEnvironment env{}; env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); auto& cur_icd = env.get_test_icd(0); cur_icd.set_min_icd_interface_version(5); cur_icd.set_icd_api_version(VK_API_VERSION_1_0); InstWrapper inst{env.vulkan_functions}; inst.create_info.add_extensions({VK_KHR_WIN32_SURFACE_EXTENSION_NAME}); inst.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT); InstWrapper inst2{env.vulkan_functions}; inst2.CheckCreate(); ASSERT_EQ(nullptr, env.vulkan_functions.vkGetInstanceProcAddr(inst2.inst, "vkCreateWin32SurfaceKHR")); } // When ICD doesn't support the surface creation, the loader should handle it TEST(WsiTests, CreateSurfaceWin32NoICDCreateSupport) { FrameworkEnvironment env{}; env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); auto& cur_icd = env.get_test_icd(0); cur_icd.set_min_icd_interface_version(5); cur_icd.set_icd_api_version(VK_API_VERSION_1_0); cur_icd.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME}); cur_icd.add_instance_extension({VK_KHR_WIN32_SURFACE_EXTENSION_NAME}); cur_icd.enable_icd_wsi = false; InstWrapper inst{env.vulkan_functions}; inst.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WIN32_SURFACE_EXTENSION_NAME}); inst.CheckCreate(); VkSurfaceKHR surface{VK_NULL_HANDLE}; VkWin32SurfaceCreateInfoKHR surf_create_info{VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR}; ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateWin32SurfaceKHR(inst, &surf_create_info, nullptr, &surface)); ASSERT_TRUE(surface != VK_NULL_HANDLE); // ASSERT_EQ(cur_icd.is_using_icd_wsi, UsingICDProvidedWSI::not_using); env.vulkan_functions.vkDestroySurfaceKHR(inst, surface, nullptr); } // When ICD does support the surface creation, the loader should delegat handle it to the ICD TEST(WsiTests, CreateSurfaceWin32ICDSupport) { FrameworkEnvironment env{}; env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); auto& cur_icd = env.get_test_icd(0); cur_icd.set_min_icd_interface_version(5); cur_icd.set_icd_api_version(VK_API_VERSION_1_0); cur_icd.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME}); cur_icd.add_instance_extension({VK_KHR_WIN32_SURFACE_EXTENSION_NAME}); cur_icd.enable_icd_wsi = true; InstWrapper inst{env.vulkan_functions}; inst.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WIN32_SURFACE_EXTENSION_NAME}); inst.CheckCreate(); VkSurfaceKHR surface{VK_NULL_HANDLE}; VkWin32SurfaceCreateInfoKHR surf_create_info{VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR}; ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateWin32SurfaceKHR(inst, &surf_create_info, nullptr, &surface)); ASSERT_TRUE(surface != VK_NULL_HANDLE); // ASSERT_EQ(cur_icd.is_using_icd_wsi, UsingICDProvidedWSI::not_using); env.vulkan_functions.vkDestroySurfaceKHR(inst, surface, nullptr); } // Some drivers supporting vkCreateWin32SurfaceKHR, and at least one that doesn't TEST(WsiTests, CreateSurfaceWin32MixedICDSupport) { FrameworkEnvironment env{}; for (uint32_t icd = 0; icd < 3; ++icd) { Extension first_ext{VK_KHR_SURFACE_EXTENSION_NAME}; Extension second_ext{VK_KHR_WIN32_SURFACE_EXTENSION_NAME}; env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); auto& cur_icd = env.get_test_icd(icd); cur_icd.icd_api_version = VK_API_VERSION_1_0; cur_icd.add_instance_extensions({first_ext, second_ext}); if (icd < 2) { // Only enable ICD for first two cur_icd.enable_icd_wsi = true; } } InstWrapper instance(env.vulkan_functions); instance.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WIN32_SURFACE_EXTENSION_NAME}); instance.CheckCreate(); VkSurfaceKHR surface{VK_NULL_HANDLE}; VkWin32SurfaceCreateInfoKHR surf_create_info{VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR}; ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateWin32SurfaceKHR(instance.inst, &surf_create_info, nullptr, &surface)); ASSERT_TRUE(surface != VK_NULL_HANDLE); // ASSERT_EQ(cur_icd.is_using_icd_wsi, UsingICDProvidedWSI::not_using); env.vulkan_functions.vkDestroySurfaceKHR(instance.inst, surface, nullptr); } TEST(WsiTests, GetPhysicalDeviceWin32PresentNoICDSupport) { FrameworkEnvironment env{}; env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); auto& cur_icd = env.get_test_icd(0); cur_icd.set_min_icd_interface_version(5); cur_icd.set_icd_api_version(VK_API_VERSION_1_0); cur_icd.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME}); cur_icd.add_instance_extension({VK_KHR_WIN32_SURFACE_EXTENSION_NAME}); cur_icd.physical_devices.emplace_back("physical_device_0"); cur_icd.enable_icd_wsi = false; InstWrapper inst{env.vulkan_functions}; inst.create_info.add_extensions( {VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WIN32_SURFACE_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_EXTENSION_NAME}); inst.CheckCreate(); uint32_t driver_count = 1; VkPhysicalDevice physical_device; ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &driver_count, &physical_device)); ASSERT_EQ(driver_count, 1U); DebugUtilsWrapper log{inst}; CreateDebugUtilsMessenger(log); auto res = env.vulkan_functions.vkGetPhysicalDeviceWin32PresentationSupportKHR(physical_device, 0); ASSERT_EQ(res, VK_FALSE); ASSERT_TRUE(log.find("ICD for selected physical device does not export vkGetPhysicalDeviceWin32PresentationSupportKHR!")); } TEST(WsiTests, GetPhysicalDeviceWin32PresentICDSupport) { FrameworkEnvironment env{}; env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); auto& cur_icd = env.get_test_icd(0); cur_icd.set_min_icd_interface_version(5); cur_icd.set_icd_api_version(VK_API_VERSION_1_0); cur_icd.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME}); cur_icd.add_instance_extension({VK_KHR_WIN32_SURFACE_EXTENSION_NAME}); cur_icd.physical_devices.emplace_back("physical_device_0"); cur_icd.enable_icd_wsi = true; InstWrapper inst{env.vulkan_functions}; inst.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WIN32_SURFACE_EXTENSION_NAME}); inst.CheckCreate(); uint32_t driver_count = 1; VkPhysicalDevice physical_device; ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &driver_count, &physical_device)); ASSERT_EQ(driver_count, 1U); ASSERT_EQ(VK_TRUE, env.vulkan_functions.vkGetPhysicalDeviceWin32PresentationSupportKHR(physical_device, 0)); } TEST(WsiTests, Win32GetPhysicalDeviceSurfaceSupportKHR) { FrameworkEnvironment env{}; const uint32_t max_device_count = 4; for (uint32_t icd = 0; icd < max_device_count; ++icd) { Extension first_ext{VK_KHR_SURFACE_EXTENSION_NAME}; Extension second_ext{VK_KHR_WIN32_SURFACE_EXTENSION_NAME}; env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); auto& cur_icd = env.get_test_icd(icd); cur_icd.icd_api_version = VK_API_VERSION_1_0; cur_icd.set_min_icd_interface_version(5); cur_icd.add_instance_extensions({first_ext, second_ext}); std::string dev_name = "phys_dev_" + std::to_string(icd); cur_icd.physical_devices.emplace_back(dev_name.c_str()); cur_icd.physical_devices.back().add_queue_family_properties({{VK_QUEUE_GRAPHICS_BIT, 1, 0, {1, 1, 1}}, true}); cur_icd.enable_icd_wsi = true; } InstWrapper instance(env.vulkan_functions); instance.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WIN32_SURFACE_EXTENSION_NAME}); instance.CheckCreate(); VkSurfaceKHR surface{VK_NULL_HANDLE}; VkWin32SurfaceCreateInfoKHR surf_create_info{VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR}; ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateWin32SurfaceKHR(instance.inst, &surf_create_info, nullptr, &surface)); ASSERT_TRUE(surface != VK_NULL_HANDLE); // ASSERT_EQ(driver.is_using_icd_wsi, UsingICDProvidedWSI::not_using); uint32_t device_count = max_device_count; std::array phys_devs; ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumeratePhysicalDevices(instance.inst, &device_count, phys_devs.data())); ASSERT_EQ(device_count, max_device_count); for (uint32_t pd = 0; pd < max_device_count; ++pd) { VkBool32 supported = VK_FALSE; ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkGetPhysicalDeviceSurfaceSupportKHR(phys_devs[pd], 0, surface, &supported)); } env.vulkan_functions.vkDestroySurfaceKHR(instance.inst, surface, nullptr); } #endif #if defined(VK_USE_PLATFORM_XCB_KHR) // When ICD doesn't support the extension, create instance should fail TEST(WsiTests, CreateSurfaceXCBNoICDSupport) { FrameworkEnvironment env{}; env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); auto& cur_icd = env.get_test_icd(0); cur_icd.set_min_icd_interface_version(5); cur_icd.set_icd_api_version(VK_API_VERSION_1_0); cur_icd.enable_icd_wsi = false; InstWrapper inst{env.vulkan_functions}; inst.create_info.add_extensions({VK_KHR_XCB_SURFACE_EXTENSION_NAME}); inst.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT); InstWrapper inst2{env.vulkan_functions}; inst2.CheckCreate(); ASSERT_EQ(nullptr, env.vulkan_functions.vkGetInstanceProcAddr(inst2.inst, "vkCreateXcbSurfaceKHR")); } // When ICD doesn't support the surface creation, the loader should handle it TEST(WsiTests, CreateSurfaceXCBNoICDCreateSupport) { FrameworkEnvironment env{}; env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); auto& cur_icd = env.get_test_icd(0); cur_icd.set_min_icd_interface_version(5); cur_icd.set_icd_api_version(VK_API_VERSION_1_0); cur_icd.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME}); cur_icd.add_instance_extension({VK_KHR_XCB_SURFACE_EXTENSION_NAME}); cur_icd.enable_icd_wsi = false; InstWrapper inst{env.vulkan_functions}; inst.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_XCB_SURFACE_EXTENSION_NAME}); inst.CheckCreate(); VkXcbSurfaceCreateInfoKHR xcb_createInfo{VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR}; VkSurfaceKHR surface{VK_NULL_HANDLE}; ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateXcbSurfaceKHR(inst, &xcb_createInfo, nullptr, &surface)); ASSERT_TRUE(surface != VK_NULL_HANDLE); env.vulkan_functions.vkDestroySurfaceKHR(inst, surface, nullptr); } // When ICD does support the surface creation, the loader should delegat handle it to the ICD TEST(WsiTests, CreateSurfaceXCBICDSupport) { FrameworkEnvironment env{}; env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); auto& cur_icd = env.get_test_icd(0); cur_icd.set_min_icd_interface_version(5); cur_icd.set_icd_api_version(VK_API_VERSION_1_0); cur_icd.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME}); cur_icd.add_instance_extension({VK_KHR_XCB_SURFACE_EXTENSION_NAME}); cur_icd.enable_icd_wsi = true; InstWrapper inst{env.vulkan_functions}; inst.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_XCB_SURFACE_EXTENSION_NAME}); inst.CheckCreate(); VkXcbSurfaceCreateInfoKHR xcb_createInfo{VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR}; VkSurfaceKHR surface{VK_NULL_HANDLE}; ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateXcbSurfaceKHR(inst, &xcb_createInfo, nullptr, &surface)); ASSERT_TRUE(surface != VK_NULL_HANDLE); env.vulkan_functions.vkDestroySurfaceKHR(inst, surface, nullptr); } // Some drivers supporting vkCreateXcbSurfaceKHR, and at least one that doesn't TEST(WsiTests, CreateSurfaceXCBMixedICDSupport) { FrameworkEnvironment env{}; for (uint32_t icd = 0; icd < 3; ++icd) { Extension first_ext{VK_KHR_SURFACE_EXTENSION_NAME}; Extension second_ext{VK_KHR_XCB_SURFACE_EXTENSION_NAME}; env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); auto& cur_icd = env.get_test_icd(icd); cur_icd.icd_api_version = VK_API_VERSION_1_0; cur_icd.add_instance_extensions({first_ext, second_ext}); if (icd < 2) { // Only enable ICD for first two cur_icd.enable_icd_wsi = true; } } InstWrapper instance(env.vulkan_functions); instance.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_XCB_SURFACE_EXTENSION_NAME}); instance.CheckCreate(); VkXcbSurfaceCreateInfoKHR xcb_createInfo{VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR}; VkSurfaceKHR surface{VK_NULL_HANDLE}; ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateXcbSurfaceKHR(instance.inst, &xcb_createInfo, nullptr, &surface)); ASSERT_TRUE(surface != VK_NULL_HANDLE); env.vulkan_functions.vkDestroySurfaceKHR(instance.inst, surface, nullptr); } TEST(WsiTests, GetPhysicalDeviceXcbPresentNoICDSupport) { FrameworkEnvironment env{}; env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); auto& cur_icd = env.get_test_icd(0); cur_icd.set_min_icd_interface_version(5); cur_icd.set_icd_api_version(VK_API_VERSION_1_0); cur_icd.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME}); cur_icd.add_instance_extension({VK_KHR_XCB_SURFACE_EXTENSION_NAME}); cur_icd.physical_devices.emplace_back("physical_device_0"); cur_icd.enable_icd_wsi = false; InstWrapper inst{env.vulkan_functions}; inst.create_info.add_extensions( {VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_XCB_SURFACE_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_EXTENSION_NAME}); inst.CheckCreate(); uint32_t driver_count = 1; VkPhysicalDevice physical_device; ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &driver_count, &physical_device)); ASSERT_EQ(driver_count, 1U); DebugUtilsWrapper log{inst}; CreateDebugUtilsMessenger(log); auto res = env.vulkan_functions.vkGetPhysicalDeviceXcbPresentationSupportKHR(physical_device, 0, nullptr, 0); ASSERT_EQ(res, VK_FALSE); ASSERT_TRUE(log.find("ICD for selected physical device does not export vkGetPhysicalDeviceXcbPresentationSupportKHR!")); } TEST(WsiTests, GetPhysicalDeviceXcbPresentICDSupport) { FrameworkEnvironment env{}; env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); auto& cur_icd = env.get_test_icd(0); cur_icd.set_min_icd_interface_version(5); cur_icd.set_icd_api_version(VK_API_VERSION_1_0); cur_icd.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME}); cur_icd.add_instance_extension({VK_KHR_XCB_SURFACE_EXTENSION_NAME}); cur_icd.physical_devices.emplace_back("physical_device_0"); cur_icd.enable_icd_wsi = true; InstWrapper inst{env.vulkan_functions}; inst.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_XCB_SURFACE_EXTENSION_NAME}); inst.CheckCreate(); uint32_t driver_count = 1; VkPhysicalDevice physical_device; ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &driver_count, &physical_device)); ASSERT_EQ(driver_count, 1U); ASSERT_EQ(VK_TRUE, env.vulkan_functions.vkGetPhysicalDeviceXcbPresentationSupportKHR(physical_device, 0, nullptr, 0)); } TEST(WsiTests, XcbGetPhysicalDeviceSurfaceSupportKHR) { FrameworkEnvironment env{}; const uint32_t max_device_count = 4; for (uint32_t icd = 0; icd < max_device_count; ++icd) { Extension first_ext{VK_KHR_SURFACE_EXTENSION_NAME}; Extension second_ext{VK_KHR_XCB_SURFACE_EXTENSION_NAME}; env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); auto& cur_icd = env.get_test_icd(icd); cur_icd.icd_api_version = VK_API_VERSION_1_0; cur_icd.set_min_icd_interface_version(5); cur_icd.add_instance_extensions({first_ext, second_ext}); std::string dev_name = "phys_dev_" + std::to_string(icd); cur_icd.physical_devices.emplace_back(dev_name.c_str()); cur_icd.physical_devices.back().add_queue_family_properties({{VK_QUEUE_GRAPHICS_BIT, 1, 0, {1, 1, 1}}, true}); cur_icd.enable_icd_wsi = true; } InstWrapper instance(env.vulkan_functions); instance.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_XCB_SURFACE_EXTENSION_NAME}); instance.CheckCreate(); VkSurfaceKHR surface{VK_NULL_HANDLE}; VkXcbSurfaceCreateInfoKHR xcb_createInfo{VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR}; ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateXcbSurfaceKHR(instance.inst, &xcb_createInfo, nullptr, &surface)); ASSERT_TRUE(surface != VK_NULL_HANDLE); // ASSERT_EQ(cur_icd.is_using_icd_wsi, UsingICDProvidedWSI::not_using); uint32_t device_count = max_device_count; std::array phys_devs; ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumeratePhysicalDevices(instance.inst, &device_count, phys_devs.data())); ASSERT_EQ(device_count, max_device_count); for (uint32_t pd = 0; pd < max_device_count; ++pd) { VkBool32 supported = VK_FALSE; ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkGetPhysicalDeviceSurfaceSupportKHR(phys_devs[pd], 0, surface, &supported)); } env.vulkan_functions.vkDestroySurfaceKHR(instance.inst, surface, nullptr); } #endif #if defined(VK_USE_PLATFORM_XLIB_KHR) // When ICD doesn't support the extension, create instance should fail TEST(WsiTests, CreateSurfaceXLIBNoICDSupport) { FrameworkEnvironment env{}; env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); auto& cur_icd = env.get_test_icd(0); cur_icd.set_min_icd_interface_version(5); cur_icd.set_icd_api_version(VK_API_VERSION_1_0); cur_icd.enable_icd_wsi = false; InstWrapper inst{env.vulkan_functions}; inst.create_info.add_extensions({VK_KHR_XLIB_SURFACE_EXTENSION_NAME}); inst.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT); InstWrapper inst2{env.vulkan_functions}; inst2.CheckCreate(); ASSERT_EQ(nullptr, env.vulkan_functions.vkGetInstanceProcAddr(inst2.inst, "vkCreateXlibSurfaceKHR")); } // When ICD doesn't support the surface creation, the loader should handle it TEST(WsiTests, CreateSurfaceXLIBNoICDCreateSupport) { FrameworkEnvironment env{}; env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); auto& cur_icd = env.get_test_icd(0); cur_icd.set_min_icd_interface_version(5); cur_icd.set_icd_api_version(VK_API_VERSION_1_0); cur_icd.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME}); cur_icd.add_instance_extension({VK_KHR_XLIB_SURFACE_EXTENSION_NAME}); cur_icd.enable_icd_wsi = false; InstWrapper inst{env.vulkan_functions}; inst.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_XLIB_SURFACE_EXTENSION_NAME}); inst.CheckCreate(); VkXlibSurfaceCreateInfoKHR createInfo{VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR}; VkSurfaceKHR surface; ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateXlibSurfaceKHR(inst, &createInfo, nullptr, &surface)); ASSERT_TRUE(surface != VK_NULL_HANDLE); env.vulkan_functions.vkDestroySurfaceKHR(inst, surface, nullptr); } // When ICD does support the surface creation, the loader should delegat handle it to the ICD TEST(WsiTests, CreateSurfaceXLIBICDSupport) { FrameworkEnvironment env{}; env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); auto& cur_icd = env.get_test_icd(0); cur_icd.set_min_icd_interface_version(5); cur_icd.set_icd_api_version(VK_API_VERSION_1_0); cur_icd.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME}); cur_icd.add_instance_extension({VK_KHR_XLIB_SURFACE_EXTENSION_NAME}); cur_icd.enable_icd_wsi = true; InstWrapper inst{env.vulkan_functions}; inst.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_XLIB_SURFACE_EXTENSION_NAME}); inst.CheckCreate(); VkXlibSurfaceCreateInfoKHR createInfo{VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR}; VkSurfaceKHR surface; ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateXlibSurfaceKHR(inst, &createInfo, nullptr, &surface)); ASSERT_TRUE(surface != VK_NULL_HANDLE); env.vulkan_functions.vkDestroySurfaceKHR(inst, surface, nullptr); } // Some drivers supporting vkCreateXlibSurfaceKHR, and at least one that doesn't TEST(WsiTests, CreateSurfaceXLIBMixedICDSupport) { FrameworkEnvironment env{}; for (uint32_t icd = 0; icd < 3; ++icd) { Extension first_ext{VK_KHR_SURFACE_EXTENSION_NAME}; Extension second_ext{VK_KHR_XLIB_SURFACE_EXTENSION_NAME}; env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); auto& cur_icd = env.get_test_icd(icd); cur_icd.icd_api_version = VK_API_VERSION_1_0; cur_icd.add_instance_extensions({first_ext, second_ext}); if (icd < 2) { // Only enable ICD for first two cur_icd.enable_icd_wsi = true; } } InstWrapper instance(env.vulkan_functions); instance.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_XLIB_SURFACE_EXTENSION_NAME}); instance.CheckCreate(); VkXlibSurfaceCreateInfoKHR createInfo{VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR}; VkSurfaceKHR surface; ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateXlibSurfaceKHR(instance.inst, &createInfo, nullptr, &surface)); ASSERT_TRUE(surface != VK_NULL_HANDLE); env.vulkan_functions.vkDestroySurfaceKHR(instance.inst, surface, nullptr); } TEST(WsiTests, GetPhysicalDeviceXlibPresentNoICDSupport) { FrameworkEnvironment env{}; env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); auto& cur_icd = env.get_test_icd(0); cur_icd.set_min_icd_interface_version(5); cur_icd.set_icd_api_version(VK_API_VERSION_1_0); cur_icd.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME}); cur_icd.add_instance_extension({VK_KHR_XLIB_SURFACE_EXTENSION_NAME}); cur_icd.physical_devices.emplace_back("physical_device_0"); cur_icd.enable_icd_wsi = false; InstWrapper inst{env.vulkan_functions}; inst.create_info.add_extensions( {VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_XLIB_SURFACE_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_EXTENSION_NAME}); inst.CheckCreate(); uint32_t driver_count = 1; VkPhysicalDevice physical_device; ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &driver_count, &physical_device)); ASSERT_EQ(driver_count, 1U); DebugUtilsWrapper log{inst}; CreateDebugUtilsMessenger(log); auto res = env.vulkan_functions.vkGetPhysicalDeviceXlibPresentationSupportKHR(physical_device, 0, nullptr, 0); ASSERT_EQ(res, VK_FALSE); ASSERT_TRUE(log.find("ICD for selected physical device does not export vkGetPhysicalDeviceXlibPresentationSupportKHR!")); } TEST(WsiTests, GetPhysicalDeviceXlibPresentICDSupport) { FrameworkEnvironment env{}; env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); auto& cur_icd = env.get_test_icd(0); cur_icd.set_min_icd_interface_version(5); cur_icd.set_icd_api_version(VK_API_VERSION_1_0); cur_icd.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME}); cur_icd.add_instance_extension({VK_KHR_XLIB_SURFACE_EXTENSION_NAME}); cur_icd.physical_devices.emplace_back("physical_device_0"); cur_icd.enable_icd_wsi = true; InstWrapper inst{env.vulkan_functions}; inst.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_XLIB_SURFACE_EXTENSION_NAME}); inst.CheckCreate(); uint32_t driver_count = 1; VkPhysicalDevice physical_device; ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &driver_count, &physical_device)); ASSERT_EQ(driver_count, 1U); ASSERT_EQ(VK_TRUE, env.vulkan_functions.vkGetPhysicalDeviceXlibPresentationSupportKHR(physical_device, 0, nullptr, 0)); } TEST(WsiTests, XlibGetPhysicalDeviceSurfaceSupportKHR) { FrameworkEnvironment env{}; const uint32_t max_device_count = 4; for (uint32_t icd = 0; icd < max_device_count; ++icd) { Extension first_ext{VK_KHR_SURFACE_EXTENSION_NAME}; Extension second_ext{VK_KHR_XLIB_SURFACE_EXTENSION_NAME}; env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); auto& cur_icd = env.get_test_icd(icd); cur_icd.icd_api_version = VK_API_VERSION_1_0; cur_icd.set_min_icd_interface_version(5); cur_icd.add_instance_extensions({first_ext, second_ext}); std::string dev_name = "phys_dev_" + std::to_string(icd); cur_icd.physical_devices.emplace_back(dev_name.c_str()); cur_icd.physical_devices.back().add_queue_family_properties({{VK_QUEUE_GRAPHICS_BIT, 1, 0, {1, 1, 1}}, true}); cur_icd.enable_icd_wsi = true; } InstWrapper instance(env.vulkan_functions); instance.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_XLIB_SURFACE_EXTENSION_NAME}); instance.CheckCreate(); VkSurfaceKHR surface{VK_NULL_HANDLE}; VkXlibSurfaceCreateInfoKHR createInfo{VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR}; ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateXlibSurfaceKHR(instance.inst, &createInfo, nullptr, &surface)); ASSERT_TRUE(surface != VK_NULL_HANDLE); // ASSERT_EQ(driver.is_using_icd_wsi, UsingICDProvidedWSI::not_using); uint32_t device_count = max_device_count; std::array phys_devs; ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumeratePhysicalDevices(instance.inst, &device_count, phys_devs.data())); ASSERT_EQ(device_count, max_device_count); for (uint32_t pd = 0; pd < max_device_count; ++pd) { VkBool32 supported = VK_FALSE; ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkGetPhysicalDeviceSurfaceSupportKHR(phys_devs[pd], 0, surface, &supported)); } env.vulkan_functions.vkDestroySurfaceKHR(instance.inst, surface, nullptr); } #endif #if defined(VK_USE_PLATFORM_WAYLAND_KHR) // When ICD doesn't support the extension, create instance should fail TEST(WsiTests, CreateSurfaceWaylandNoICDSupport) { FrameworkEnvironment env{}; env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); auto& cur_icd = env.get_test_icd(0); cur_icd.set_min_icd_interface_version(5); cur_icd.set_icd_api_version(VK_API_VERSION_1_0); cur_icd.enable_icd_wsi = false; InstWrapper inst{env.vulkan_functions}; inst.create_info.add_extensions({VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME}); inst.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT); InstWrapper inst2{env.vulkan_functions}; inst2.CheckCreate(); ASSERT_EQ(nullptr, env.vulkan_functions.vkGetInstanceProcAddr(inst2.inst, "vkCreateWaylandSurfaceKHR")); } // When ICD doesn't support the surface creation, the loader should handle it TEST(WsiTests, CreateSurfaceWaylandNoICDCreateSupport) { FrameworkEnvironment env{}; env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); auto& cur_icd = env.get_test_icd(0); cur_icd.set_min_icd_interface_version(5); cur_icd.set_icd_api_version(VK_API_VERSION_1_0); cur_icd.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME}); cur_icd.add_instance_extension({VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME}); cur_icd.enable_icd_wsi = false; InstWrapper inst{env.vulkan_functions}; inst.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME}); inst.CheckCreate(); VkWaylandSurfaceCreateInfoKHR createInfo{VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR}; VkSurfaceKHR surface; ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateWaylandSurfaceKHR(inst, &createInfo, nullptr, &surface)); ASSERT_TRUE(surface != VK_NULL_HANDLE); env.vulkan_functions.vkDestroySurfaceKHR(inst, surface, nullptr); } // When ICD does support the surface creation, the loader should delegat handle it to the ICD TEST(WsiTests, CreateSurfaceWaylandICDSupport) { FrameworkEnvironment env{}; env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); auto& cur_icd = env.get_test_icd(0); cur_icd.set_min_icd_interface_version(5); cur_icd.set_icd_api_version(VK_API_VERSION_1_0); cur_icd.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME}); cur_icd.add_instance_extension({VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME}); cur_icd.enable_icd_wsi = true; InstWrapper inst{env.vulkan_functions}; inst.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME}); inst.CheckCreate(); VkWaylandSurfaceCreateInfoKHR createInfo{VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR}; VkSurfaceKHR surface; ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateWaylandSurfaceKHR(inst, &createInfo, nullptr, &surface)); ASSERT_TRUE(surface != VK_NULL_HANDLE); env.vulkan_functions.vkDestroySurfaceKHR(inst, surface, nullptr); } // Some drivers supporting vkCreateWaylandSurfaceKHR, and at least one that doesn't TEST(WsiTests, CreateSurfaceWaylandMixedICDSupport) { FrameworkEnvironment env{}; for (uint32_t icd = 0; icd < 3; ++icd) { Extension first_ext{VK_KHR_SURFACE_EXTENSION_NAME}; Extension second_ext{VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME}; env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); auto& cur_icd = env.get_test_icd(icd); cur_icd.icd_api_version = VK_API_VERSION_1_0; cur_icd.add_instance_extensions({first_ext, second_ext}); if (icd < 2) { // Only enable ICD for first two cur_icd.enable_icd_wsi = true; } } InstWrapper instance(env.vulkan_functions); instance.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME}); instance.CheckCreate(); VkWaylandSurfaceCreateInfoKHR createInfo{VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR}; VkSurfaceKHR surface; ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateWaylandSurfaceKHR(instance.inst, &createInfo, nullptr, &surface)); ASSERT_TRUE(surface != VK_NULL_HANDLE); env.vulkan_functions.vkDestroySurfaceKHR(instance.inst, surface, nullptr); } TEST(WsiTests, GetPhysicalDeviceWaylandPresentNoICDSupport) { FrameworkEnvironment env{}; env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); auto& cur_icd = env.get_test_icd(0); cur_icd.set_min_icd_interface_version(5); cur_icd.set_icd_api_version(VK_API_VERSION_1_0); cur_icd.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME}); cur_icd.add_instance_extension({VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME}); cur_icd.physical_devices.emplace_back("physical_device_0"); cur_icd.enable_icd_wsi = false; InstWrapper inst{env.vulkan_functions}; inst.create_info.add_extensions( {VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_EXTENSION_NAME}); inst.CheckCreate(); uint32_t driver_count = 1; VkPhysicalDevice physical_device; ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &driver_count, &physical_device)); ASSERT_EQ(driver_count, 1U); DebugUtilsWrapper log{inst}; CreateDebugUtilsMessenger(log); auto res = env.vulkan_functions.vkGetPhysicalDeviceWaylandPresentationSupportKHR(physical_device, 0, nullptr); ASSERT_EQ(res, VK_FALSE); ASSERT_TRUE(log.find("ICD for selected physical device does not export vkGetPhysicalDeviceWaylandPresentationSupportKHR!")); } TEST(WsiTests, GetPhysicalDeviceWaylandPresentICDSupport) { FrameworkEnvironment env{}; env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); auto& cur_icd = env.get_test_icd(0); cur_icd.set_min_icd_interface_version(5); cur_icd.set_icd_api_version(VK_API_VERSION_1_0); cur_icd.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME}); cur_icd.add_instance_extension({VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME}); cur_icd.physical_devices.emplace_back("physical_device_0"); cur_icd.enable_icd_wsi = true; InstWrapper inst{env.vulkan_functions}; inst.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME}); inst.CheckCreate(); uint32_t driver_count = 1; VkPhysicalDevice physical_device; ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &driver_count, &physical_device)); ASSERT_EQ(driver_count, 1U); ASSERT_EQ(VK_TRUE, env.vulkan_functions.vkGetPhysicalDeviceWaylandPresentationSupportKHR(physical_device, 0, nullptr)); } TEST(WsiTests, WaylandGetPhysicalDeviceSurfaceSupportKHR) { FrameworkEnvironment env{}; const uint32_t max_device_count = 4; for (uint32_t icd = 0; icd < max_device_count; ++icd) { Extension first_ext{VK_KHR_SURFACE_EXTENSION_NAME}; Extension second_ext{VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME}; env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); auto& cur_icd = env.get_test_icd(icd); cur_icd.icd_api_version = VK_API_VERSION_1_0; cur_icd.set_min_icd_interface_version(5); cur_icd.add_instance_extensions({first_ext, second_ext}); std::string dev_name = "phys_dev_" + std::to_string(icd); cur_icd.physical_devices.emplace_back(dev_name.c_str()); cur_icd.physical_devices.back().add_queue_family_properties({{VK_QUEUE_GRAPHICS_BIT, 1, 0, {1, 1, 1}}, true}); cur_icd.enable_icd_wsi = true; } InstWrapper instance(env.vulkan_functions); instance.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME}); instance.CheckCreate(); VkSurfaceKHR surface{VK_NULL_HANDLE}; VkWaylandSurfaceCreateInfoKHR createInfo{VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR}; ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateWaylandSurfaceKHR(instance.inst, &createInfo, nullptr, &surface)); ASSERT_TRUE(surface != VK_NULL_HANDLE); // ASSERT_EQ(cur_icd.is_using_icd_wsi, UsingICDProvidedWSI::not_using); uint32_t device_count = max_device_count; std::array phys_devs; ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumeratePhysicalDevices(instance.inst, &device_count, phys_devs.data())); ASSERT_EQ(device_count, max_device_count); for (uint32_t pd = 0; pd < max_device_count; ++pd) { VkBool32 supported = VK_FALSE; ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkGetPhysicalDeviceSurfaceSupportKHR(phys_devs[pd], 0, surface, &supported)); } env.vulkan_functions.vkDestroySurfaceKHR(instance.inst, surface, nullptr); } #endif TEST(WsiTests, ForgetEnableSurfaceExtensions) { FrameworkEnvironment env{}; env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); auto& driver = env.get_test_icd(); setup_WSI_in_ICD(driver); MockQueueFamilyProperties family_props{{VK_QUEUE_GRAPHICS_BIT, 1, 0, {1, 1, 1}}, true}; driver.physical_devices.emplace_back("physical_device_0"); driver.physical_devices.back().queue_family_properties.push_back(family_props); driver.physical_devices.back().add_extension("VK_KHR_swapchain"); InstWrapper inst{env.vulkan_functions}; inst.create_info.add_extension("VK_KHR_surface"); ASSERT_NO_FATAL_FAILURE(inst.CheckCreate()); VkSurfaceKHR surface{}; ASSERT_FALSE(create_surface(inst, surface)); } TEST(WsiTests, SwapchainFunctional) { FrameworkEnvironment env{}; env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); auto& driver = env.get_test_icd(); setup_WSI_in_ICD(driver); MockQueueFamilyProperties family_props{{VK_QUEUE_GRAPHICS_BIT, 1, 0, {1, 1, 1}}, true}; driver.physical_devices.emplace_back("physical_device_0"); driver.physical_devices.back().queue_family_properties.push_back(family_props); driver.physical_devices.back().add_extension("VK_KHR_swapchain"); InstWrapper inst{env.vulkan_functions}; setup_WSI_in_create_instance(inst); inst.CheckCreate(); VkSurfaceKHR surface{}; create_surface(inst, surface); VkPhysicalDevice phys_dev = inst.GetPhysDev(); { // Use GDPA to get functions DeviceWrapper dev{inst}; dev.create_info.add_extension("VK_KHR_swapchain"); dev.create_info.add_device_queue(DeviceQueueCreateInfo{}.add_priority(0.0f)); ASSERT_NO_FATAL_FAILURE(dev.CheckCreate(phys_dev)); VkSwapchainKHR swapchain{}; VkSwapchainCreateInfoKHR swap_create_info{}; swap_create_info.surface = surface; DeviceFunctions funcs{*inst.functions, dev}; ASSERT_EQ(VK_SUCCESS, funcs.vkCreateSwapchainKHR(dev, &swap_create_info, nullptr, &swapchain)); uint32_t count = 0; ASSERT_EQ(VK_SUCCESS, funcs.vkGetSwapchainImagesKHR(dev, swapchain, &count, nullptr)); ASSERT_GT(count, 0U); std::array images; ASSERT_EQ(VK_SUCCESS, funcs.vkGetSwapchainImagesKHR(dev, swapchain, &count, images.data())); funcs.vkDestroySwapchainKHR(dev, swapchain, nullptr); } { // Use GIPA gotten functions DeviceWrapper dev{inst}; dev.create_info.add_extension("VK_KHR_swapchain"); dev.create_info.add_device_queue(DeviceQueueCreateInfo{}.add_priority(0.0f)); ASSERT_NO_FATAL_FAILURE(dev.CheckCreate(phys_dev)); PFN_vkCreateSwapchainKHR inst_CreateSwapchainKHR = inst.load("vkCreateSwapchainKHR"); PFN_vkGetSwapchainImagesKHR inst_GetSwapchainImagesKHR = inst.load("vkGetSwapchainImagesKHR"); PFN_vkDestroySwapchainKHR inst_DestroySwapchainKHR = inst.load("vkDestroySwapchainKHR"); ASSERT_TRUE(nullptr != inst_CreateSwapchainKHR); ASSERT_TRUE(nullptr != inst_GetSwapchainImagesKHR); ASSERT_TRUE(nullptr != inst_DestroySwapchainKHR); VkSwapchainKHR swapchain{}; VkSwapchainCreateInfoKHR swap_create_info{}; swap_create_info.surface = surface; ASSERT_EQ(VK_SUCCESS, inst_CreateSwapchainKHR(dev, &swap_create_info, nullptr, &swapchain)); uint32_t count = 0; ASSERT_EQ(VK_SUCCESS, inst_GetSwapchainImagesKHR(dev, swapchain, &count, nullptr)); ASSERT_GT(count, 0U); std::array images; ASSERT_EQ(VK_SUCCESS, inst_GetSwapchainImagesKHR(dev, swapchain, &count, images.data())); inst_DestroySwapchainKHR(dev, swapchain, nullptr); } { // forget to enable the extension DeviceWrapper dev{inst}; ASSERT_NO_FATAL_FAILURE(dev.CheckCreate(phys_dev)); DeviceFunctions funcs{*inst.functions, dev}; ASSERT_EQ(funcs.vkCreateSwapchainKHR, nullptr); ASSERT_EQ(funcs.vkGetSwapchainImagesKHR, nullptr); ASSERT_EQ(funcs.vkDestroySwapchainKHR, nullptr); } { // forget to set the surface DeviceWrapper dev{inst}; dev.create_info.add_extension("VK_KHR_swapchain"); dev.create_info.add_device_queue(DeviceQueueCreateInfo{}.add_priority(0.0f)); dev.CheckCreate(phys_dev); VkSwapchainKHR swapchain{}; VkSwapchainCreateInfoKHR swap_create_info{}; DeviceFunctions funcs{*inst.functions, dev}; ASSERT_DEATH(funcs.vkCreateSwapchainKHR(dev, &swap_create_info, nullptr, &swapchain), ""); } env.vulkan_functions.vkDestroySurfaceKHR(inst.inst, surface, nullptr); }