Add more WSI tests, and fix some compiler warnings.
authorMark Young <marky@lunarg.com>
Mon, 20 Dec 2021 22:49:09 +0000 (15:49 -0700)
committerMark Young <marky@lunarg.com>
Fri, 7 Jan 2022 23:56:38 +0000 (16:56 -0700)
Simplified the WSI tests so that they don't actually create the
platform surfaces and attach them.  Instead, the test_icd framework
allows us to simply provide a dummy.  This allows the tests to work
in the regresssion framework.  Because of this, removed the separate
test_wsi test and merged it into test_regression.

Fixed several compiler warnings from my previous change as well.

tests/CMakeLists.txt
tests/framework/icd/test_icd.cpp
tests/loader_phys_dev_inst_ext_tests.cpp
tests/loader_wsi_tests.cpp

index 207796abbe51dca0397ff3a557405a88babd59ac..f54825432631a3249302868b0b84b26eaf766342 100644 (file)
@@ -34,31 +34,9 @@ add_executable(
         loader_regression_tests.cpp
         loader_phys_dev_inst_ext_tests.cpp
         loader_version_tests.cpp
-        loader_unknown_ext_tests.cpp)
-target_link_libraries(test_regression PRIVATE testing_dependencies)
-
-add_executable(
-    test_wsi
-        loader_testing_main.cpp
+        loader_unknown_ext_tests.cpp
         loader_wsi_tests.cpp)
-target_link_libraries(test_wsi PRIVATE testing_dependencies)
-
-if(UNIX AND NOT APPLE) # i.e. Linux
-    if(BUILD_WSI_XCB_SUPPORT)
-        target_include_directories(test_wsi PRIVATE ${XCB_INCLUDE_DIRS})
-        target_link_libraries(test_wsi PRIVATE ${XCB_LIBRARIES})
-    endif()
-
-    if(BUILD_WSI_XLIB_SUPPORT)
-        target_include_directories(test_wsi PRIVATE ${X11_INCLUDE_DIR})
-        target_link_libraries(test_wsi PRIVATE ${X11_LIBRARIES})
-    endif()
-
-    if(BUILD_WSI_WAYLAND_SUPPORT)
-        target_include_directories(test_wsi PRIVATE ${WAYLAND_CLIENT_INCLUDE_DIR})
-        target_link_libraries(test_wsi PRIVATE ${WAYLAND_CLIENT_LIBRARIES})
-    endif()
-endif()
+target_link_libraries(test_regression PRIVATE testing_dependencies)
 
 add_executable(
     test_threading
index 497b9d3507e0b89ccda601b8da120cce203f7947..f97082305cd71d5be0d1c9f8e459166af8c779e2 100644 (file)
@@ -347,6 +347,11 @@ VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateWin32SurfaceKHR(VkInstance instance,
     }
     return VK_SUCCESS;
 }
+
+VKAPI_ATTR VkBool32 VKAPI_CALL test_vkGetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice physicalDevice,
+                                                                                   uint32_t queueFamilyIndex) {
+    return VK_TRUE;
+}
 #endif  // VK_USE_PLATFORM_WIN32_KHR
 
 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
@@ -364,8 +369,13 @@ VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateWaylandSurfaceKHR(VkInstance instanc
     }
     return VK_SUCCESS;
 }
-#endif  // VK_USE_PLATFORM_WAYLAND_KHR
 
+VKAPI_ATTR VkBool32 VKAPI_CALL test_vkGetPhysicalDeviceWaylandPresentationSupportKHR(VkPhysicalDevice physicalDevice,
+                                                                                     uint32_t queueFamilyIndex,
+                                                                                     struct wl_display* display) {
+    return VK_TRUE;
+}
+#endif  // VK_USE_PLATFORM_WAYLAND_KHR
 #ifdef VK_USE_PLATFORM_XCB_KHR
 VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateXcbSurfaceKHR(VkInstance instance, const VkXcbSurfaceCreateInfoKHR* pCreateInfo,
                                                           const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface) {
@@ -381,6 +391,13 @@ VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateXcbSurfaceKHR(VkInstance instance, c
     }
     return VK_SUCCESS;
 }
+
+VKAPI_ATTR VkBool32 VKAPI_CALL test_vkGetPhysicalDeviceXcbPresentationSupportKHR(VkPhysicalDevice physicalDevice,
+                                                                                 uint32_t queueFamilyIndex,
+                                                                                 xcb_connection_t* connection,
+                                                                                 xcb_visualid_t visual_id) {
+    return VK_TRUE;
+}
 #endif  // VK_USE_PLATFORM_XCB_KHR
 
 #ifdef VK_USE_PLATFORM_XLIB_KHR
@@ -398,6 +415,12 @@ VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateXlibSurfaceKHR(VkInstance instance,
     }
     return VK_SUCCESS;
 }
+
+VKAPI_ATTR VkBool32 VKAPI_CALL test_vkGetPhysicalDeviceXlibPresentationSupportKHR(VkPhysicalDevice physicalDevice,
+                                                                                  uint32_t queueFamilyIndex, Display* dpy,
+                                                                                  VisualID visualID) {
+    return VK_TRUE;
+}
 #endif  // VK_USE_PLATFORM_XLIB_KHR
 
 #ifdef VK_USE_PLATFORM_DIRECTFB_EXT
@@ -416,6 +439,12 @@ VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateDirectFBSurfaceEXT(VkInstance instan
     }
     return VK_SUCCESS;
 }
+
+VKAPI_ATTR VkBool32 VKAPI_CALL test_vkGetPhysicalDeviceDirectFBPresentationSupportEXT(VkPhysicalDevice physicalDevice,
+                                                                                      uint32_t queueFamilyIndex, IDirectFB* dfb) {
+    return VK_TRUE;
+}
+
 #endif  // VK_USE_PLATFORM_DIRECTFB_EXT
 
 #ifdef VK_USE_PLATFORM_MACOS_MVK
@@ -503,15 +532,25 @@ VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateScreenSurfaceQNX(VkInstance instance
     }
     return VK_SUCCESS;
 }
+
+VKAPI_ATTR VkBool32 VKAPI_CALL test_vkGetPhysicalDeviceScreenPresentationSupportQNX(VkPhysicalDevice physicalDevice,
+                                                                                    uint32_t queueFamilyIndex,
+                                                                                    struct _screen_window* window) {
+    return VK_TRUE;
+}
 #endif  // VK_USE_PLATFORM_SCREEN_QNX
 
 VKAPI_ATTR void VKAPI_CALL test_vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface,
                                                     const VkAllocationCallbacks* pAllocator) {
     if (surface != VK_NULL_HANDLE) {
         uint64_t fake_surf_handle = (uint64_t)(surface);
-        auto found_iter = icd.surface_handles.erase(
-            std::remove(icd.surface_handles.begin(), icd.surface_handles.end(), fake_surf_handle), icd.surface_handles.end());
-        if (found_iter == icd.surface_handles.end()) {
+        auto found_iter = std::find(icd.surface_handles.begin(), icd.surface_handles.end(), fake_surf_handle);
+        if (found_iter != icd.surface_handles.end()) {
+            // Remove it from the list
+            icd.surface_handles.erase(found_iter);
+            // Delete the handle
+            delete (uint8_t*)fake_surf_handle;
+        } else {
             assert(false && "Surface not found during destroy!");
         }
     }
@@ -882,26 +921,41 @@ PFN_vkVoidFunction get_instance_func_wsi(VkInstance instance, const char* pName)
         if (string_eq(pName, "vkCreateWaylandSurfaceKHR")) {
             return TO_VOID_PFN(test_vkCreateWaylandSurfaceKHR);
         }
+        if (string_eq(pName, "vkGetPhysicalDeviceWaylandPresentationSupportKHR")) {
+            return TO_VOID_PFN(test_vkGetPhysicalDeviceWaylandPresentationSupportKHR);
+        }
 #endif
 #ifdef VK_USE_PLATFORM_XCB_KHR
         if (string_eq(pName, "vkCreateXcbSurfaceKHR")) {
             return TO_VOID_PFN(test_vkCreateXcbSurfaceKHR);
         }
+        if (string_eq(pName, "vkGetPhysicalDeviceXcbPresentationSupportKHR")) {
+            return TO_VOID_PFN(test_vkGetPhysicalDeviceXcbPresentationSupportKHR);
+        }
 #endif
 #ifdef VK_USE_PLATFORM_XLIB_KHR
         if (string_eq(pName, "vkCreateXlibSurfaceKHR")) {
             return TO_VOID_PFN(test_vkCreateXlibSurfaceKHR);
         }
+        if (string_eq(pName, "vkGetPhysicalDeviceXlibPresentationSupportKHR")) {
+            return TO_VOID_PFN(test_vkGetPhysicalDeviceXlibPresentationSupportKHR);
+        }
 #endif
 #ifdef VK_USE_PLATFORM_WIN32_KHR
         if (string_eq(pName, "vkCreateWin32SurfaceKHR")) {
             return TO_VOID_PFN(test_vkCreateWin32SurfaceKHR);
         }
+        if (string_eq(pName, "vkGetPhysicalDeviceWin32PresentationSupportKHR")) {
+            return TO_VOID_PFN(test_vkGetPhysicalDeviceWin32PresentationSupportKHR);
+        }
 #endif
 #ifdef VK_USE_PLATFORM_DIRECTFB_EXT
         if (string_eq(pName, "vkCreateDirectFBSurfaceEXT")) {
             return TO_VOID_PFN(test_vkCreateDirectFBSurfaceEXT);
         }
+        if (string_eq(pName, "vkGetPhysicalDeviceDirectFBPresentationSupportEXT")) {
+            return TO_VOID_PFN(test_vkGetPhysicalDeviceDirectFBPresentationSupportEXT);
+        }
 #endif  // VK_USE_PLATFORM_DIRECTFB_EXT
 
 #ifdef VK_USE_PLATFORM_MACOS_MVK
@@ -926,6 +980,9 @@ PFN_vkVoidFunction get_instance_func_wsi(VkInstance instance, const char* pName)
         if (string_eq(pName, "vkCreateScreenSurfaceQNX")) {
             return TO_VOID_PFN(test_vkCreateScreenSurfaceQNX);
         }
+        if (string_eq(pName, "vkGetPhysicalDeviceScreenPresentationSupportQNX")) {
+            return TO_VOID_PFN(test_vkGetPhysicalDeviceScreenPresentationSupportQNX);
+        }
 #endif  // VK_USE_PLATFORM_SCREEN_QNX
 
         if (string_eq(pName, "vkDestroySurfaceKHR")) {
index 5173d44adb5906558a4a4be8d9ccc29e81289916..93aef9f6a69c5eec92e3c7c383591aee3cbeb022 100644 (file)
@@ -2619,11 +2619,18 @@ TEST_F(LoaderInstPhysDevExts, PhysDevDispPropsKHRNoICDSupport) {
     ASSERT_EQ(GetPhysicalDeviceDisplayProperties, nullptr);
 }
 
+VkDisplayKHR CreateRandomDisplay() {
+    return (VkDisplayKHR)(((rand() % 0xFFFFFFFBull) << 12) * (rand() % 0xFFFFFFFull) + 1); }
+
+VkDisplayModeKHR CreateRandomDisplayMode() {
+    return (VkDisplayModeKHR)(((rand() % 0xFFFFFFFBull) << 12) * (rand() % 0xFFFFFFFull) + 1);
+}
+
 // Fill in random but valid data into the display property data struct for the current physical device
 static void FillInRandomDisplayPropData(std::vector<VkDisplayPropertiesKHR>& props) {
     props.resize((rand() % 5) + 1);
     for (uint32_t i = 0; i < props.size(); ++i) {
-        props[i].display = (VkDisplayKHR)((rand() % 0xFFFFFFF) + 1);
+        props[i].display = CreateRandomDisplay();
         props[i].physicalDimensions.width = static_cast<uint32_t>((rand() % 0xFFF) + 1);
         props[i].physicalDimensions.height = static_cast<uint32_t>((rand() % 0xFFF) + 1);
         props[i].physicalResolution.width = static_cast<uint32_t>((rand() % 0xFFF) + 1);
@@ -2820,7 +2827,7 @@ TEST_F(LoaderInstPhysDevExts, PhysDevDispPlanePropsKHRNoICDSupport) {
 static void FillInRandomDisplayPlanePropData(std::vector<VkDisplayPlanePropertiesKHR>& props) {
     props.resize((rand() % 5) + 1);
     for (uint32_t i = 0; i < props.size(); ++i) {
-        props[i].currentDisplay = (VkDisplayKHR)((rand() % 0xFFFFFFF) + 1);
+        props[i].currentDisplay = CreateRandomDisplay();
         props[i].currentStackIndex = static_cast<uint32_t>((rand() % 0xFFF) + (rand() % 0xFFF) + 1);
     }
 }
@@ -3006,7 +3013,7 @@ TEST_F(LoaderInstPhysDevExts, GetDispPlaneSupDispsKHRNoICDSupport) {
 static void GenerateRandomDisplays(std::vector<VkDisplayKHR>& disps) {
     disps.resize((rand() % 5) + 1);
     for (uint32_t i = 0; i < disps.size(); ++i) {
-        disps[i] = (VkDisplayKHR)((rand() % 0xFFFFFFF) + 1);
+        disps[i] = CreateRandomDisplay();
     }
 }
 
@@ -3189,7 +3196,7 @@ TEST_F(LoaderInstPhysDevExts, GetDispModePropsKHRNoICDSupport) {
 static void GenerateRandomDisplayModeProps(std::vector<VkDisplayModePropertiesKHR>& disps) {
     disps.resize((rand() % 5) + 1);
     for (uint32_t i = 0; i < disps.size(); ++i) {
-        disps[i].displayMode = (VkDisplayModeKHR)((rand() % 0xFFFFFFF) + 1);
+        disps[i].displayMode = CreateRandomDisplayMode();
         disps[i].parameters.visibleRegion.width = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
         disps[i].parameters.visibleRegion.height = static_cast<uint32_t>((rand() % 0xFFFFFFF) + 1);
         disps[i].parameters.refreshRate = 1 << (rand() % 8);
@@ -3375,9 +3382,6 @@ TEST_F(LoaderInstPhysDevExts, GetDispModesKHRNoICDSupport) {
     ASSERT_EQ(CreateDisplayMode, nullptr);
 }
 
-// Fill in random but valid data into the display modes for the current physical device
-static void GenerateRandomDisplayMode(VkDisplayModeKHR& mode) { mode = (VkDisplayModeKHR)((rand() % 0xFFFFFFF) + 1); }
-
 // Compare the display modes
 static void CompareDisplayModes(const VkDisplayModeKHR& disps1, VkDisplayModeKHR& disps2) { ASSERT_EQ(disps1, disps2); }
 
@@ -3387,7 +3391,7 @@ TEST_F(LoaderInstPhysDevExts, GetDispModesKHRInstanceAndICDSupport) {
     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
     env.get_test_icd(0).add_instance_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
     env.get_test_icd(0).physical_devices.push_back({});
-    GenerateRandomDisplayMode(env.get_test_icd(0).physical_devices.back().display_mode);
+    env.get_test_icd(0).physical_devices.back().display_mode = CreateRandomDisplayMode();
 
     InstWrapper instance(env.vulkan_functions);
     instance.create_info.add_extension({VK_KHR_DISPLAY_EXTENSION_NAME});
@@ -3455,7 +3459,7 @@ TEST_F(LoaderInstPhysDevExts, GetDispModesKHRMixed) {
 
             // Still set physical device properties (so we can determine if device is correct API version)
             FillInRandomDeviceProps(cur_dev.properties, device_version, rand_vendor_id, rand_driver_vers);
-            GenerateRandomDisplayMode(cur_dev.display_mode);
+            cur_dev.display_mode = CreateRandomDisplayMode();
         }
     }
 
index 9e9acc906cbbddd005e457bb745f89ffae2d6b10..36d74daae3116b876485c08074d41785ce476c13 100644 (file)
 #include <X11/Xutil.h>
 #endif
 
-class RegressionTests : public ::testing::Test {
+class WsiTests : public ::testing::Test {
    protected:
     virtual void SetUp() {
         env = std::unique_ptr<FrameworkEnvironment>(new FrameworkEnvironment());
         env->add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
     }
+
     virtual void TearDown() { env.reset(); }
     std::unique_ptr<FrameworkEnvironment> env;
 
@@ -46,239 +47,537 @@ class RegressionTests : public ::testing::Test {
 
 #if defined(VK_USE_PLATFORM_WIN32_KHR)
 
-// MS-Windows event handling function:
-LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { return DefWindowProcA(hWnd, uMsg, wParam, lParam); }
+// When ICD doesn't support the extension, create instance should fail
+TEST_F(WsiTests, CreateSurfaceWin32NoICDSupport) {
+    auto& driver = env->get_test_icd();
+    driver.set_icd_api_version(VK_MAKE_VERSION(1, 0, 0));
+    driver.set_min_icd_interface_version(5);
+    driver.enable_icd_wsi = false;
+
+    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_F(WsiTests, CreateSurfaceWin32NoICDCreateSupport) {
+    auto& driver = env->get_test_icd();
+    driver.set_icd_api_version(VK_MAKE_VERSION(1, 0, 0));
+    driver.set_min_icd_interface_version(5);
+    driver.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME});
+    driver.add_instance_extension({VK_KHR_WIN32_SURFACE_EXTENSION_NAME});
+    driver.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(driver.is_using_icd_wsi, UsingICDProvidedWSI::not_using);
 
-TEST_F(RegressionTests, CreateSurfaceWin32) {
+    env->vulkan_functions.vkDestroySurfaceKHR(inst, surface, nullptr);
+}
+
+// When ICD does support the surface creation, the loader should  delegat handle it to the ICD
+TEST_F(WsiTests, CreateSurfaceWin32ICDSupport) {
     auto& driver = env->get_test_icd();
     driver.set_icd_api_version(VK_MAKE_VERSION(1, 0, 0));
     driver.set_min_icd_interface_version(5);
-    driver.add_instance_extension(Extension(VK_KHR_SURFACE_EXTENSION_NAME));
-    driver.add_instance_extension(Extension(VK_KHR_WIN32_SURFACE_EXTENSION_NAME));
+    driver.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME});
+    driver.add_instance_extension({VK_KHR_WIN32_SURFACE_EXTENSION_NAME});
     driver.enable_icd_wsi = true;
 
     InstWrapper inst{env->vulkan_functions};
-    inst.create_info = driver.GetVkInstanceCreateInfo();
+    inst.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WIN32_SURFACE_EXTENSION_NAME});
     inst.CheckCreate();
 
-    WNDCLASSEX win_class;
-    const char* app_short_name = "loader_surface_test";
-    HINSTANCE h_instance = GetModuleHandle(nullptr);  // Windows Instance
-    HWND h_wnd = nullptr;                             // window handle
-
-    // Initialize the window class structure:
-    win_class.cbSize = sizeof(WNDCLASSEX);
-    win_class.style = CS_HREDRAW | CS_VREDRAW;
-    win_class.lpfnWndProc = WndProc;
-    win_class.cbClsExtra = 0;
-    win_class.cbWndExtra = 0;
-    win_class.hInstance = h_instance;
-    win_class.hIcon = LoadIconA(nullptr, IDI_APPLICATION);
-    win_class.hCursor = LoadCursor(nullptr, IDC_ARROW);
-    win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
-    win_class.lpszMenuName = nullptr;
-    win_class.lpszClassName = app_short_name;
-    win_class.hIconSm = LoadIconA(nullptr, IDI_WINLOGO);
-
-    // Register window class:
-    EXPECT_TRUE(RegisterClassExA(&win_class) != NULL);
-
-    // Create window with the registered class:
-    RECT wr = {0, 0, width, height};
-    AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
-    h_wnd = CreateWindowExA(0,
-                            app_short_name,  // class name
-                            app_short_name,  // app name
-                            // WS_VISIBLE | WS_SYSMENU |
-                            WS_OVERLAPPEDWINDOW,  // window style
-                            width, height,        // x/y coords
-                            wr.right - wr.left,   // width
-                            wr.bottom - wr.top,   // height
-                            nullptr,              // handle to parent
-                            nullptr,              // handle to menu
-                            h_instance,           // hInstance
-                            nullptr);             // no extra parameters
-    EXPECT_TRUE(h_wnd != nullptr);
-
-    VkSurfaceKHR surface{};
-    VkWin32SurfaceCreateInfoKHR surf_create_info{};
-    surf_create_info.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
-    surf_create_info.hwnd = h_wnd;
-    surf_create_info.hinstance = h_instance;
+    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(driver.is_using_icd_wsi, UsingICDProvidedWSI::not_using);
 
     env->vulkan_functions.vkDestroySurfaceKHR(inst, surface, nullptr);
-    DestroyWindow(h_wnd);
 }
 
-#endif
+// Some drivers supporting vkCreateWin32SurfaceKHR, and at least one that doesn't
+TEST_F(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;
+        }
+    }
 
-#if defined(VK_USE_PLATFORM_XCB_KHR)
-TEST_F(RegressionTests, CreateSurfaceXCB) {
+    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);
+
+    env.vulkan_functions.vkDestroySurfaceKHR(instance.inst, surface, nullptr);
+}
+
+TEST_F(WsiTests, GetPhysicalDeviceWin32PresentNoICDSupport) {
     auto& driver = env->get_test_icd();
     driver.set_icd_api_version(VK_MAKE_VERSION(1, 0, 0));
     driver.set_min_icd_interface_version(5);
-    driver.add_instance_extension(Extension(VK_KHR_SURFACE_EXTENSION_NAME));
-    driver.add_instance_extension(Extension(VK_KHR_XCB_SURFACE_EXTENSION_NAME));
+    driver.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME});
+    driver.add_instance_extension({VK_KHR_WIN32_SURFACE_EXTENSION_NAME});
+    driver.physical_devices.emplace_back("physical_device_0");
+    driver.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();
+
+    uint32_t driver_count = 1;
+    VkPhysicalDevice physical_device;
+    ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &driver_count, &physical_device));
+    ASSERT_EQ(driver_count, 1);
+
+    ASSERT_DEATH(env->vulkan_functions.vkGetPhysicalDeviceWin32PresentationSupportKHR(physical_device, 0), "");
+}
+
+TEST_F(WsiTests, GetPhysicalDeviceWin32PresentICDSupport) {
+    auto& driver = env->get_test_icd();
+    driver.set_icd_api_version(VK_MAKE_VERSION(1, 0, 0));
+    driver.set_min_icd_interface_version(5);
+    driver.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME});
+    driver.add_instance_extension({VK_KHR_WIN32_SURFACE_EXTENSION_NAME});
+    driver.physical_devices.emplace_back("physical_device_0");
     driver.enable_icd_wsi = true;
 
     InstWrapper inst{env->vulkan_functions};
-    inst.create_info = driver.GetVkInstanceCreateInfo();
+    inst.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WIN32_SURFACE_EXTENSION_NAME});
     inst.CheckCreate();
 
-    xcb_connection_t* xcb_connection;
-    xcb_screen_t* xcb_screen;
-    xcb_window_t xcb_window;
+    uint32_t driver_count = 1;
+    VkPhysicalDevice physical_device;
+    ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &driver_count, &physical_device));
+    ASSERT_EQ(driver_count, 1);
 
-    //--Init Connection--
-    const xcb_setup_t* setup;
-    xcb_screen_iterator_t iter;
-    int scr;
+    ASSERT_EQ(VK_TRUE, env->vulkan_functions.vkGetPhysicalDeviceWin32PresentationSupportKHR(physical_device, 0));
+}
+#endif
 
-    // API guarantees non-null xcb_connection
-    xcb_connection = xcb_connect(nullptr, &scr);
-    int conn_error = xcb_connection_has_error(xcb_connection);
-    ASSERT_EQ(conn_error, 0);
+#if defined(VK_USE_PLATFORM_XCB_KHR)
+// When ICD doesn't support the extension, create instance should fail
+TEST_F(WsiTests, CreateSurfaceXCBNoICDSupport) {
+    auto& driver = env->get_test_icd();
+    driver.set_icd_api_version(VK_MAKE_VERSION(1, 0, 0));
+    driver.set_min_icd_interface_version(5);
+    driver.enable_icd_wsi = false;
 
-    setup = xcb_get_setup(xcb_connection);
-    iter = xcb_setup_roots_iterator(setup);
-    while (scr-- > 0) {
-        xcb_screen_next(&iter);
-    }
+    InstWrapper inst{env->vulkan_functions};
+    inst.create_info.add_extensions({VK_KHR_XCB_SURFACE_EXTENSION_NAME});
+    inst.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
 
-    xcb_screen = iter.data;
+    InstWrapper inst2{env->vulkan_functions};
+    inst2.CheckCreate();
 
-    xcb_window = xcb_generate_id(xcb_connection);
-    xcb_create_window(xcb_connection, XCB_COPY_FROM_PARENT, xcb_window, xcb_screen->root, 0, 0, width, height, 0,
-                      XCB_WINDOW_CLASS_INPUT_OUTPUT, xcb_screen->root_visual, 0, nullptr);
+    ASSERT_EQ(nullptr, env->vulkan_functions.vkGetInstanceProcAddr(inst2.inst, "vkCreateXcbSurfaceKHR"));
+}
 
-    xcb_intern_atom_cookie_t cookie = xcb_intern_atom(xcb_connection, 1, 12, "WM_PROTOCOLS");
-    xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(xcb_connection, cookie, 0);
-    free(reply);
+// When ICD doesn't support the surface creation, the loader should handle it
+TEST_F(WsiTests, CreateSurfaceXCBNoICDCreateSupport) {
+    auto& driver = env->get_test_icd();
+    driver.set_icd_api_version(VK_MAKE_VERSION(1, 0, 0));
+    driver.set_min_icd_interface_version(5);
+    driver.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME});
+    driver.add_instance_extension({VK_KHR_XCB_SURFACE_EXTENSION_NAME});
+    driver.enable_icd_wsi = false;
 
-    VkXcbSurfaceCreateInfoKHR xcb_createInfo;
-    xcb_createInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
-    xcb_createInfo.pNext = nullptr;
-    xcb_createInfo.flags = 0;
-    xcb_createInfo.connection = xcb_connection;
-    xcb_createInfo.window = xcb_window;
+    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{};
+    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_F(WsiTests, CreateSurfaceXCBICDSupport) {
+    auto& driver = env->get_test_icd();
+    driver.set_icd_api_version(VK_MAKE_VERSION(1, 0, 0));
+    driver.set_min_icd_interface_version(5);
+    driver.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME});
+    driver.add_instance_extension({VK_KHR_XCB_SURFACE_EXTENSION_NAME});
+    driver.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_F(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();
 
-    xcb_destroy_window(xcb_connection, xcb_window);
-    xcb_disconnect(xcb_connection);
+    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_F(WsiTests, GetPhysicalDeviceXcbPresentNoICDSupport) {
+    auto& driver = env->get_test_icd();
+    driver.set_icd_api_version(VK_MAKE_VERSION(1, 0, 0));
+    driver.set_min_icd_interface_version(5);
+    driver.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME});
+    driver.add_instance_extension({VK_KHR_XCB_SURFACE_EXTENSION_NAME});
+    driver.physical_devices.emplace_back("physical_device_0");
+    driver.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();
+
+    uint32_t driver_count = 1;
+    VkPhysicalDevice physical_device;
+    ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &driver_count, &physical_device));
+    ASSERT_EQ(driver_count, 1);
+
+    ASSERT_DEATH(env->vulkan_functions.vkGetPhysicalDeviceXcbPresentationSupportKHR(physical_device, 0, nullptr, 0), "");
+}
+
+TEST_F(WsiTests, GetPhysicalDeviceXcbPresentICDSupport) {
+    auto& driver = env->get_test_icd();
+    driver.set_icd_api_version(VK_MAKE_VERSION(1, 0, 0));
+    driver.set_min_icd_interface_version(5);
+    driver.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME});
+    driver.add_instance_extension({VK_KHR_XCB_SURFACE_EXTENSION_NAME});
+    driver.physical_devices.emplace_back("physical_device_0");
+    driver.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, 1);
+
+    ASSERT_EQ(VK_TRUE, env->vulkan_functions.vkGetPhysicalDeviceXcbPresentationSupportKHR(physical_device, 0, nullptr, 0));
 }
 #endif
 
 #if defined(VK_USE_PLATFORM_XLIB_KHR)
-TEST_F(RegressionTests, CreateSurfaceXLIB) {
+// When ICD doesn't support the extension, create instance should fail
+TEST_F(WsiTests, CreateSurfaceXLIBNoICDSupport) {
     auto& driver = env->get_test_icd();
     driver.set_icd_api_version(VK_MAKE_VERSION(1, 0, 0));
     driver.set_min_icd_interface_version(5);
-    driver.add_instance_extension(Extension(VK_KHR_SURFACE_EXTENSION_NAME));
-    driver.add_instance_extension(Extension(VK_KHR_XLIB_SURFACE_EXTENSION_NAME));
-    driver.enable_icd_wsi = true;
+    driver.enable_icd_wsi = false;
 
     InstWrapper inst{env->vulkan_functions};
-    inst.create_info = driver.GetVkInstanceCreateInfo();
+    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_F(WsiTests, CreateSurfaceXLIBNoICDCreateSupport) {
+    auto& driver = env->get_test_icd();
+    driver.set_icd_api_version(VK_MAKE_VERSION(1, 0, 0));
+    driver.set_min_icd_interface_version(5);
+    driver.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME});
+    driver.add_instance_extension({VK_KHR_XLIB_SURFACE_EXTENSION_NAME});
+    driver.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();
 
-    Display* xlib_display;
-    Window xlib_window;
+    VkXlibSurfaceCreateInfoKHR createInfo{VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR};
 
-    long visualMask = VisualScreenMask;
-    int numberOfVisuals;
+    VkSurfaceKHR surface;
+    ASSERT_EQ(VK_SUCCESS, env->vulkan_functions.vkCreateXlibSurfaceKHR(inst, &createInfo, nullptr, &surface));
+    ASSERT_TRUE(surface != VK_NULL_HANDLE);
 
-    xlib_display = XOpenDisplay(nullptr);
-    ASSERT_NE(xlib_display, nullptr);
+    env->vulkan_functions.vkDestroySurfaceKHR(inst, surface, nullptr);
+}
 
-    XVisualInfo vInfoTemplate = {};
-    vInfoTemplate.screen = DefaultScreen(xlib_display);
-    XVisualInfo* visualInfo = XGetVisualInfo(xlib_display, visualMask, &vInfoTemplate, &numberOfVisuals);
-    xlib_window = XCreateWindow(xlib_display, RootWindow(xlib_display, vInfoTemplate.screen), 0, 0, width, height, 0,
-                                visualInfo->depth, InputOutput, visualInfo->visual, 0, nullptr);
+// When ICD does support the surface creation, the loader should  delegat handle it to the ICD
+TEST_F(WsiTests, CreateSurfaceXLIBICDSupport) {
+    auto& driver = env->get_test_icd();
+    driver.set_icd_api_version(VK_MAKE_VERSION(1, 0, 0));
+    driver.set_min_icd_interface_version(5);
+    driver.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME});
+    driver.add_instance_extension({VK_KHR_XLIB_SURFACE_EXTENSION_NAME});
+    driver.enable_icd_wsi = true;
 
-    XSync(xlib_display, false);
-    XFree(visualInfo);
+    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;
-    createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
-    createInfo.pNext = nullptr;
-    createInfo.flags = 0;
-    createInfo.dpy = xlib_display;
-    createInfo.window = xlib_window;
+    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_F(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};
 
-    XDestroyWindow(xlib_display, xlib_window);
-    XCloseDisplay(xlib_display);
+    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_F(WsiTests, GetPhysicalDeviceXlibPresentNoICDSupport) {
+    auto& driver = env->get_test_icd();
+    driver.set_icd_api_version(VK_MAKE_VERSION(1, 0, 0));
+    driver.set_min_icd_interface_version(5);
+    driver.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME});
+    driver.add_instance_extension({VK_KHR_XLIB_SURFACE_EXTENSION_NAME});
+    driver.physical_devices.emplace_back("physical_device_0");
+    driver.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();
+
+    uint32_t driver_count = 1;
+    VkPhysicalDevice physical_device;
+    ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &driver_count, &physical_device));
+    ASSERT_EQ(driver_count, 1);
+
+    ASSERT_DEATH(env->vulkan_functions.vkGetPhysicalDeviceXlibPresentationSupportKHR(physical_device, 0, nullptr, 0), "");
+}
+
+TEST_F(WsiTests, GetPhysicalDeviceXlibPresentICDSupport) {
+    auto& driver = env->get_test_icd();
+    driver.set_icd_api_version(VK_MAKE_VERSION(1, 0, 0));
+    driver.set_min_icd_interface_version(5);
+    driver.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME});
+    driver.add_instance_extension({VK_KHR_XLIB_SURFACE_EXTENSION_NAME});
+    driver.physical_devices.emplace_back("physical_device_0");
+    driver.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, 1);
+
+    ASSERT_EQ(VK_TRUE, env->vulkan_functions.vkGetPhysicalDeviceXlibPresentationSupportKHR(physical_device, 0, nullptr, 0));
 }
 #endif
 
 #if defined(VK_USE_PLATFORM_WAYLAND_KHR)
+// When ICD doesn't support the extension, create instance should fail
+TEST_F(WsiTests, CreateSurfaceWaylandNoICDSupport) {
+    auto& driver = env->get_test_icd();
+    driver.set_icd_api_version(VK_MAKE_VERSION(1, 0, 0));
+    driver.set_min_icd_interface_version(5);
+    driver.enable_icd_wsi = false;
 
-struct WaylandState {
-    wl_display* display{};
-    wl_registry* registry{};
-    wl_compositor* compositor{};
-    wl_surface* surface{};
-};
+    InstWrapper inst{env->vulkan_functions};
+    inst.create_info.add_extensions({VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME});
+    inst.CheckCreate(VK_ERROR_EXTENSION_NOT_PRESENT);
 
-static void wayland_registry_global(void* data, struct wl_registry* registry, uint32_t id, const char* interface,
-                                    uint32_t version) {
-    WaylandState* wayland = static_cast<WaylandState*>(data);
-    if (string_eq(interface, "wl_compositor")) {
-        wayland->compositor = (struct wl_compositor*)wl_registry_bind(registry, id, &wl_compositor_interface, 1);
-        wayland->surface = wl_compositor_create_surface(wayland->compositor);
-    }
+    InstWrapper inst2{env->vulkan_functions};
+    inst2.CheckCreate();
+
+    ASSERT_EQ(nullptr, env->vulkan_functions.vkGetInstanceProcAddr(inst2.inst, "vkCreateWaylandSurfaceKHR"));
 }
-static void wayland_registry_global_remove(void* data, struct wl_registry* registry, uint32_t id) {}
-static const struct wl_registry_listener wayland_registry_listener = {wayland_registry_global, wayland_registry_global_remove};
 
-TEST_F(RegressionTests, CreateSurfaceWayland) {
+// When ICD doesn't support the surface creation, the loader should handle it
+TEST_F(WsiTests, CreateSurfaceWaylandNoICDCreateSupport) {
     auto& driver = env->get_test_icd();
     driver.set_icd_api_version(VK_MAKE_VERSION(1, 0, 0));
     driver.set_min_icd_interface_version(5);
-    driver.add_instance_extension(Extension(VK_KHR_SURFACE_EXTENSION_NAME));
-    driver.add_instance_extension(Extension(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME));
-    driver.enable_icd_wsi = true;
+    driver.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME});
+    driver.add_instance_extension({VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME});
+    driver.enable_icd_wsi = false;
 
     InstWrapper inst{env->vulkan_functions};
-    inst.create_info = driver.GetVkInstanceCreateInfo();
+    inst.create_info.add_extensions({VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME});
     inst.CheckCreate();
 
-    WaylandState wayland;
+    VkWaylandSurfaceCreateInfoKHR createInfo{VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR};
 
-    wayland.display = wl_display_connect(nullptr);
-    ASSERT_NE(wayland.display, nullptr);
-    wayland.registry = wl_display_get_registry(wayland.display);
-    wl_registry_add_listener(wl_display_get_registry(wayland.display), &wayland_registry_listener, static_cast<void*>(&wayland));
-    wl_display_roundtrip(wayland.display);
-    wl_registry_destroy(wayland.registry);
+    VkSurfaceKHR surface;
+    ASSERT_EQ(VK_SUCCESS, env->vulkan_functions.vkCreateWaylandSurfaceKHR(inst, &createInfo, nullptr, &surface));
+    ASSERT_TRUE(surface != VK_NULL_HANDLE);
 
-    VkWaylandSurfaceCreateInfoKHR createInfo;
-    createInfo.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR;
-    createInfo.pNext = nullptr;
-    createInfo.flags = 0;
-    createInfo.display = wayland.display;
-    createInfo.surface = wayland.surface;
+    env->vulkan_functions.vkDestroySurfaceKHR(inst, surface, nullptr);
+}
+
+// When ICD does support the surface creation, the loader should  delegat handle it to the ICD
+TEST_F(WsiTests, CreateSurfaceWaylandICDSupport) {
+    auto& driver = env->get_test_icd();
+    driver.set_icd_api_version(VK_MAKE_VERSION(1, 0, 0));
+    driver.set_min_icd_interface_version(5);
+    driver.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME});
+    driver.add_instance_extension({VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME});
+    driver.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_F(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_F(WsiTests, GetPhysicalDeviceWaylandPresentNoICDSupport) {
+    auto& driver = env->get_test_icd();
+    driver.set_icd_api_version(VK_MAKE_VERSION(1, 0, 0));
+    driver.set_min_icd_interface_version(5);
+    driver.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME});
+    driver.add_instance_extension({VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME});
+    driver.physical_devices.emplace_back("physical_device_0");
+    driver.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();
+
+    uint32_t driver_count = 1;
+    VkPhysicalDevice physical_device;
+    ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &driver_count, &physical_device));
+    ASSERT_EQ(driver_count, 1);
+
+    ASSERT_DEATH(env->vulkan_functions.vkGetPhysicalDeviceWaylandPresentationSupportKHR(physical_device, 0, nullptr), "");
+}
+
+TEST_F(WsiTests, GetPhysicalDeviceWaylandPresentICDSupport) {
+    auto& driver = env->get_test_icd();
+    driver.set_icd_api_version(VK_MAKE_VERSION(1, 0, 0));
+    driver.set_min_icd_interface_version(5);
+    driver.add_instance_extension({VK_KHR_SURFACE_EXTENSION_NAME});
+    driver.add_instance_extension({VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME});
+    driver.physical_devices.emplace_back("physical_device_0");
+    driver.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, 1);
 
-    wl_display_disconnect(wayland.display);
+    ASSERT_EQ(VK_TRUE, env->vulkan_functions.vkGetPhysicalDeviceWaylandPresentationSupportKHR(physical_device, 0, nullptr));
 }
 #endif
\ No newline at end of file