loader: gh181 use ICD for SurfaceKHR
authorMark Young <marky@lunarg.com>
Tue, 28 Jun 2016 16:52:43 +0000 (10:52 -0600)
committerMark Young <marky@lunarg.com>
Mon, 19 Sep 2016 20:52:50 +0000 (14:52 -0600)
Use the ICD to create and destroy VkSurfaceKHR objects instead
of just performing the work in the ICD.  This only occurs if the ICD
exports the appropriate entry-points, and exposes version 3 of the
loader/icd interface.

Change-Id: I5e7bf9506318823c57ad75cf19d3f53fdfa6451e

include/vulkan/vk_icd.h
loader/loader.c
loader/loader.h
loader/table_ops.h
loader/trampoline.c
loader/wsi.c
loader/wsi.h

index a649364..39442fb 100644 (file)
@@ -28,7 +28,7 @@
 /*
  * Loader-ICD version negotiation API
  */
-#define CURRENT_LOADER_ICD_INTERFACE_VERSION 2
+#define CURRENT_LOADER_ICD_INTERFACE_VERSION 3
 #define MIN_SUPPORTED_LOADER_ICD_INTERFACE_VERSION 0
 typedef VkResult (VKAPI_PTR *PFN_vkNegotiateLoaderICDInterfaceVersion)(uint32_t *pVersion);
 /*
@@ -121,4 +121,31 @@ typedef struct {
     VkDisplayPlaneAlphaFlagBitsKHR alphaMode;
     VkExtent2D imageExtent;
 } VkIcdSurfaceDisplay;
+
+typedef struct {
+    union {
+#ifdef VK_USE_PLATFORM_MIR_KHR
+        VkIcdSurfaceMir mir_surf;
+#endif // VK_USE_PLATFORM_MIR_KHR
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+        VkIcdSurfaceWayland wayland_surf;
+#endif // VK_USE_PLATFORM_WAYLAND_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+        VkIcdSurfaceWin32 win_surf;
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_XCB_KHR
+        VkIcdSurfaceXcb xcb_surf;
+#endif // VK_USE_PLATFORM_XCB_KHR
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+        VkIcdSurfaceXlib xlib_surf;
+#endif // VK_USE_PLATFORM_XLIB_KHR
+        VkIcdSurfaceDisplay display_surf;
+    };
+    uint32_t base_size; // Size of VkIcdSurfaceBase
+    uint32_t platform_size; // Size of corresponding VkIcdSurfaceXXX
+    uint32_t non_platform_offset; // Start offset to base_size
+    uint32_t entire_size; // Size of entire VkIcdSurface
+    VkSurfaceKHR *real_icd_surfaces;
+} VkIcdSurface;
+
 #endif // VKICD_H
index 9323cff..6abd432 100644 (file)
@@ -412,7 +412,7 @@ vkSetInstanceDispatch(VkInstance instance, void *object) {
 VKAPI_ATTR VkResult VKAPI_CALL
 vkSetDeviceDispatch(VkDevice device, void *object) {
     struct loader_device *dev;
-    struct loader_icd *icd = loader_get_icd_and_device(device, &dev);
+    struct loader_icd *icd = loader_get_icd_and_device(device, &dev, NULL);
 
     if (!icd) {
         return VK_ERROR_INITIALIZATION_FAILED;
@@ -1243,8 +1243,10 @@ out:
 }
 
 struct loader_icd *loader_get_icd_and_device(const VkDevice device,
-                                             struct loader_device **found_dev) {
+                                             struct loader_device **found_dev,
+                                             uint32_t *icd_index) {
     *found_dev = NULL;
+    uint32_t index = 0;
     for (struct loader_instance *inst = loader.instances; inst;
          inst = inst->next) {
         for (struct loader_icd *icd = inst->icds; icd; icd = icd->next) {
@@ -1255,8 +1257,12 @@ struct loader_icd *loader_get_icd_and_device(const VkDevice device,
                 if (loader_get_dispatch(dev->device) ==
                     loader_get_dispatch(device)) {
                     *found_dev = dev;
+                    if (NULL != icd_index) {
+                        *icd_index = index;
+                    }
                     return icd;
                 }
+            index++;
         }
     }
     return NULL;
@@ -1634,16 +1640,21 @@ static bool loader_icd_init_entrys(struct loader_icd *icd, VkInstance inst,
     LOOKUP_GIPA(CreateDisplayModeKHR, false);
     LOOKUP_GIPA(GetDisplayPlaneCapabilitiesKHR, false);
     LOOKUP_GIPA(DestroySurfaceKHR, false);
+    LOOKUP_GIPA(CreateSwapchainKHR, false);
 #ifdef VK_USE_PLATFORM_WIN32_KHR
+    LOOKUP_GIPA(CreateWin32SurfaceKHR, false);
     LOOKUP_GIPA(GetPhysicalDeviceWin32PresentationSupportKHR, false);
 #endif
 #ifdef VK_USE_PLATFORM_XCB_KHR
+    LOOKUP_GIPA(CreateXcbSurfaceKHR, false);
     LOOKUP_GIPA(GetPhysicalDeviceXcbPresentationSupportKHR, false);
 #endif
 #ifdef VK_USE_PLATFORM_XLIB_KHR
+    LOOKUP_GIPA(CreateXlibSurfaceKHR, false);
     LOOKUP_GIPA(GetPhysicalDeviceXlibPresentationSupportKHR, false);
 #endif
 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
+    LOOKUP_GIPA(CreateWaylandSurfaceKHR, false);
     LOOKUP_GIPA(GetPhysicalDeviceWaylandPresentationSupportKHR, false);
 #endif
     LOOKUP_GIPA(GetPhysicalDeviceExternalImageFormatPropertiesNV, false);
@@ -3232,10 +3243,20 @@ loader_gpa_instance_internal(VkInstance inst, const char *pName) {
     return NULL;
 }
 
+
 static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
 loader_gpa_device_internal(VkDevice device, const char *pName) {
     struct loader_device *dev;
-    struct loader_icd *icd = loader_get_icd_and_device(device, &dev);
+    struct loader_icd *icd = loader_get_icd_and_device(device, &dev, NULL);
+
+    // Certain device entry-points still need to go through a terminator before
+    // hitting the ICD.  This could be for several reasons, but the main one
+    // is currently unwrapping an object before passing the appropriate info
+    // along to the ICD.
+    if (!strcmp(pName, "vkCreateSwapchainKHR")) {
+        return (PFN_vkVoidFunction)terminator_vkCreateSwapchainKHR;
+    }
+
     return icd->GetDeviceProcAddr(device, pName);
 }
 
@@ -4429,6 +4450,7 @@ terminator_EnumeratePhysicalDevices(VkInstance instance,
         for (j = 0; j < phys_devs[i].count && idx < copy_count; j++) {
             loader_set_dispatch((void *)&inst->phys_devs_term[idx], inst->disp);
             inst->phys_devs_term[idx].this_icd = phys_devs[i].this_icd;
+            inst->phys_devs_term[idx].icd_index = i;
             inst->phys_devs_term[idx].phys_dev = phys_devs[i].phys_devs[j];
             pPhysicalDevices[idx] =
                 (VkPhysicalDevice)&inst->phys_devs_term[idx];
index 19d28e1..a65f489 100644 (file)
@@ -209,22 +209,27 @@ struct loader_icd {
     PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV
         GetPhysicalDeviceExternalImageFormatPropertiesNV;
 #ifdef VK_USE_PLATFORM_WIN32_KHR
+    PFN_vkCreateWin32SurfaceKHR CreateWin32SurfaceKHR;
     PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR
         GetPhysicalDeviceWin32PresentationSupportKHR;
 #endif
 #ifdef VK_USE_PLATFORM_MIR_KHR
+    PFN_vkCreateMirSurfaceKHR CreateMirSurfaceKHR;
     PFN_vkGetPhysicalDeviceMirPresentationSupportKHR
         GetPhysicalDeviceMirPresentationSupportKHR;
 #endif
 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
+    PFN_vkCreateWaylandSurfaceKHR CreateWaylandSurfaceKHR;
     PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR
         GetPhysicalDeviceWaylandPresentationSupportKHR;
 #endif
 #ifdef VK_USE_PLATFORM_XCB_KHR
+    PFN_vkCreateXcbSurfaceKHR CreateXcbSurfaceKHR;
     PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR
         GetPhysicalDeviceXcbPresentationSupportKHR;
 #endif
 #ifdef VK_USE_PLATFORM_XLIB_KHR
+    PFN_vkCreateXlibSurfaceKHR CreateXlibSurfaceKHR;
     PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR
         GetPhysicalDeviceXlibPresentationSupportKHR;
 #endif
@@ -239,6 +244,7 @@ struct loader_icd {
     PFN_vkGetDisplayPlaneCapabilitiesKHR GetDisplayPlaneCapabilitiesKHR;
     PFN_vkCreateDisplayPlaneSurfaceKHR CreateDisplayPlaneSurfaceKHR;
     PFN_vkDestroySurfaceKHR DestroySurfaceKHR;
+    PFN_vkCreateSwapchainKHR CreateSwapchainKHR;
     struct loader_icd *next;
 };
 
@@ -333,6 +339,7 @@ struct loader_physical_device_tramp {
 struct loader_physical_device {
     VkLayerInstanceDispatchTable *disp; // must be first entry in structure
     struct loader_icd *this_icd;
+    uint8_t icd_index;
     VkPhysicalDevice phys_dev; // object from ICD
 };
 
@@ -500,7 +507,8 @@ VkResult loader_get_icd_loader_instance_extensions(
     const struct loader_instance *inst, struct loader_icd_libs *icd_libs,
     struct loader_extension_list *inst_exts);
 struct loader_icd *loader_get_icd_and_device(const VkDevice device,
-                                             struct loader_device **found_dev);
+                                             struct loader_device **found_dev,
+                                             uint32_t *icd_index);
 void loader_init_dispatch_dev_ext(struct loader_instance *inst,
                                   struct loader_device *dev);
 void *loader_dev_ext_gpa(struct loader_instance *inst, const char *funcName);
index cb84b87..427a7f6 100644 (file)
@@ -31,7 +31,7 @@
 
 static VkResult vkDevExtError(VkDevice dev) {
     struct loader_device *found_dev;
-    struct loader_icd *icd = loader_get_icd_and_device(dev, &found_dev);
+    struct loader_icd *icd = loader_get_icd_and_device(dev, &found_dev, NULL);
 
     if (icd)
         loader_log(icd->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
@@ -540,6 +540,20 @@ loader_lookup_device_dispatch_table(const VkLayerDispatchTable *table,
     if (!strcmp(name, "CmdExecuteCommands"))
         return (void *)table->CmdExecuteCommands;
 
+    if (!strcmp(name, "CreateSwapchainKHR")) {
+        // For CreateSwapChainKHR we need to use the entry and terminator
+        // functions to properly unwrap the SurfaceKHR object.
+        return (void *)vkCreateSwapchainKHR;
+    }
+    if (!strcmp(name, "DestroySwapchainKHR"))
+        return (void *)table->DestroySwapchainKHR;
+    if (!strcmp(name, "GetSwapchainImagesKHR"))
+        return (void *)table->GetSwapchainImagesKHR;
+    if (!strcmp(name, "AcquireNextImageKHR"))
+        return (void *)table->AcquireNextImageKHR;
+    if (!strcmp(name, "QueuePresentKHR"))
+        return (void *)table->QueuePresentKHR;
+
     return NULL;
 }
 
index 7ed168f..98b1e40 100644 (file)
@@ -751,7 +751,7 @@ vkDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
 
     loader_platform_thread_lock_mutex(&loader_lock);
 
-    struct loader_icd *icd = loader_get_icd_and_device(device, &dev);
+    struct loader_icd *icd = loader_get_icd_and_device(device, &dev, NULL);
     const struct loader_instance *inst = icd->this_instance;
     disp = loader_get_dispatch(device);
 
index a74cdb4..d38085d 100644 (file)
 #include "wsi.h"
 #include <vulkan/vk_icd.h>
 
+// The first ICD/Loader interface that support querying the SurfaceKHR from
+// the ICDs.
+#define ICD_VER_SUPPORTS_ICD_SURFACE_KHR 3
+
 static const VkExtensionProperties wsi_surface_extension_info = {
     .extensionName = VK_KHR_SURFACE_EXTENSION_NAME,
     .specVersion = VK_KHR_SURFACE_SPEC_VERSION,
@@ -207,6 +211,32 @@ terminator_DestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface,
                              const VkAllocationCallbacks *pAllocator) {
     struct loader_instance *ptr_instance = loader_get_instance(instance);
 
+// Android doesn't have to worry about multiple ICD scenario, but the rest do.
+#ifndef VK_USE_PLATFORM_ANDROID_KHR
+    VkIcdSurface *icd_surface = (VkIcdSurface *)(surface);
+    if (NULL != icd_surface->real_icd_surfaces) {
+        for (uint32_t i = 0; i < ptr_instance->total_icd_count; i++) {
+            if (ptr_instance->icd_libs.list[i].interface_version >=
+                ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
+                struct loader_icd *icd = &ptr_instance->icds[i];
+                if (NULL != icd->DestroySurfaceKHR &&
+                    NULL != (void *)icd_surface->real_icd_surfaces[i]) {
+                    icd->DestroySurfaceKHR(instance,
+                                           icd_surface->real_icd_surfaces[i],
+                                           pAllocator);
+                    icd_surface->real_icd_surfaces[i] = (VkSurfaceKHR)NULL;
+                }
+            } else {
+                // The real_icd_surface for any ICD not supporting the proper
+                // interface version should be NULL.  If not, then we have a
+                // problem.
+                assert(NULL == icd_surface->real_icd_surfaces[i]);
+            }
+        }
+        loader_instance_heap_free(ptr_instance, icd_surface->real_icd_surfaces);
+    }
+#endif // !VK_USE_PLATFORM_XLIB_KHR
+
     loader_instance_heap_free(ptr_instance, (void *)surface);
 }
 
@@ -252,6 +282,17 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceSupportKHR(
     assert(icd->GetPhysicalDeviceSurfaceSupportKHR &&
            "loader: null GetPhysicalDeviceSurfaceSupportKHR ICD pointer");
 
+// Android doesn't have to worry about multiple ICD scenario, but the rest do.
+#ifndef VK_USE_PLATFORM_ANDROID_KHR
+    VkIcdSurface *icd_surface = (VkIcdSurface *)(surface);
+    if (NULL != icd_surface->real_icd_surfaces &&
+        NULL != (void *)icd_surface->real_icd_surfaces[phys_dev->icd_index]) {
+        return icd->GetPhysicalDeviceSurfaceSupportKHR(
+            phys_dev->phys_dev, queueFamilyIndex,
+            icd_surface->real_icd_surfaces[phys_dev->icd_index], pSupported);
+    }
+#endif
+
     return icd->GetPhysicalDeviceSurfaceSupportKHR(
         phys_dev->phys_dev, queueFamilyIndex, surface, pSupported);
 }
@@ -298,6 +339,18 @@ terminator_GetPhysicalDeviceSurfaceCapabilitiesKHR(
     assert(icd->GetPhysicalDeviceSurfaceCapabilitiesKHR &&
            "loader: null GetPhysicalDeviceSurfaceCapabilitiesKHR ICD pointer");
 
+// Android doesn't have to worry about multiple ICD scenario, but the rest do.
+#ifndef VK_USE_PLATFORM_ANDROID_KHR
+    VkIcdSurface *icd_surface = (VkIcdSurface *)(surface);
+    if (NULL != icd_surface->real_icd_surfaces &&
+        NULL != (void *)icd_surface->real_icd_surfaces[phys_dev->icd_index]) {
+        return icd->GetPhysicalDeviceSurfaceCapabilitiesKHR(
+            phys_dev->phys_dev,
+            icd_surface->real_icd_surfaces[phys_dev->icd_index],
+            pSurfaceCapabilities);
+    }
+#endif
+
     return icd->GetPhysicalDeviceSurfaceCapabilitiesKHR(
         phys_dev->phys_dev, surface, pSurfaceCapabilities);
 }
@@ -345,6 +398,18 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceFormatsKHR(
     assert(icd->GetPhysicalDeviceSurfaceFormatsKHR &&
            "loader: null GetPhysicalDeviceSurfaceFormatsKHR ICD pointer");
 
+// Android doesn't have to worry about multiple ICD scenario, but the rest do.
+#ifndef VK_USE_PLATFORM_ANDROID_KHR
+    VkIcdSurface *icd_surface = (VkIcdSurface *)(surface);
+    if (NULL != icd_surface->real_icd_surfaces &&
+        NULL != (void *)icd_surface->real_icd_surfaces[phys_dev->icd_index]) {
+        return icd->GetPhysicalDeviceSurfaceFormatsKHR(
+            phys_dev->phys_dev,
+            icd_surface->real_icd_surfaces[phys_dev->icd_index],
+            pSurfaceFormatCount, pSurfaceFormats);
+    }
+#endif
+
     return icd->GetPhysicalDeviceSurfaceFormatsKHR(
         phys_dev->phys_dev, surface, pSurfaceFormatCount, pSurfaceFormats);
 }
@@ -391,6 +456,18 @@ terminator_GetPhysicalDeviceSurfacePresentModesKHR(
     assert(icd->GetPhysicalDeviceSurfacePresentModesKHR &&
            "loader: null GetPhysicalDeviceSurfacePresentModesKHR ICD pointer");
 
+// Android doesn't have to worry about multiple ICD scenario, but the rest do.
+#ifndef VK_USE_PLATFORM_ANDROID_KHR
+    VkIcdSurface *icd_surface = (VkIcdSurface *)(surface);
+    if (NULL != icd_surface->real_icd_surfaces &&
+        NULL != (void *)icd_surface->real_icd_surfaces[phys_dev->icd_index]) {
+        return icd->GetPhysicalDeviceSurfacePresentModesKHR(
+            phys_dev->phys_dev,
+            icd_surface->real_icd_surfaces[phys_dev->icd_index],
+            pPresentModeCount, pPresentModes);
+    }
+#endif
+
     return icd->GetPhysicalDeviceSurfacePresentModesKHR(
         phys_dev->phys_dev, surface, pPresentModeCount, pPresentModes);
 }
@@ -407,6 +484,40 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateSwapchainKHR(
                                     pSwapchain);
 }
 
+VKAPI_ATTR VkResult VKAPI_CALL terminator_vkCreateSwapchainKHR(
+    VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo,
+    const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchain) {
+    uint32_t icd_index = 0;
+    struct loader_device *dev;
+    struct loader_icd *icd = loader_get_icd_and_device(device, &dev, &icd_index);
+    PFN_vkCreateSwapchainKHR CreateSwapchainKHR;
+    if (NULL != icd &&
+        NULL != icd->CreateSwapchainKHR) {
+        // Android doesn't have to worry about multiple ICD scenario, but the rest do.
+#ifndef VK_USE_PLATFORM_ANDROID_KHR
+        VkIcdSurface *icd_surface = (VkIcdSurface *)(pCreateInfo->surface);
+        if (NULL != icd_surface->real_icd_surfaces) {
+            if (NULL != (void *)icd_surface->real_icd_surfaces[icd_index]) {
+                // We found the ICD, and there is an ICD KHR surface
+                // associated with it, so copy the CreateInfo struct
+                // and point it at the ICD's surface.
+                VkSwapchainCreateInfoKHR *pCreateCopy =
+                    loader_stack_alloc(sizeof(VkSwapchainCreateInfoKHR));
+                if (NULL == pCreateCopy) {
+                    return VK_ERROR_OUT_OF_HOST_MEMORY;
+                }
+                memcpy(pCreateCopy, pCreateInfo, sizeof(VkIcdSurface));
+                pCreateCopy->surface =
+                    icd_surface->real_icd_surfaces[icd_index];
+                return icd->CreateSwapchainKHR(device, pCreateCopy, pAllocator, pSwapchain);
+            }
+        }
+#endif
+        return icd->CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain);
+    }
+    return VK_SUCCESS;
+}
+
 // This is the trampoline entrypoint for DestroySwapchainKHR
 LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
 vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain,
@@ -416,22 +527,26 @@ vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain,
     disp->DestroySwapchainKHR(device, swapchain, pAllocator);
 }
 
-// This is the trampoline entrypoint for GetSwapchainImagesKHR
-LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain,
-                        uint32_t *pSwapchainImageCount,
-                        VkImage *pSwapchainImages) {
+/*
+ * This is the trampoline entrypoint
+ * for GetSwapchainImagesKHR
+ */
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainImagesKHR(
+    VkDevice device, VkSwapchainKHR swapchain, uint32_t *pSwapchainImageCount,
+    VkImage *pSwapchainImages) {
     const VkLayerDispatchTable *disp;
     disp = loader_get_dispatch(device);
     return disp->GetSwapchainImagesKHR(
         device, swapchain, pSwapchainImageCount, pSwapchainImages);
 }
 
-// This is the trampoline entrypoint for AcquireNextImageKHR
-LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain,
-                      uint64_t timeout, VkSemaphore semaphore, VkFence fence,
-                      uint32_t *pImageIndex) {
+/*
+ * This is the trampoline entrypoint
+ * for AcquireNextImageKHR
+ */
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImageKHR(
+    VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout,
+    VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex) {
     const VkLayerDispatchTable *disp;
     disp = loader_get_dispatch(device);
     return disp->AcquireNextImageKHR(device, swapchain, timeout,
@@ -468,32 +583,83 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateWin32SurfaceKHR(
 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateWin32SurfaceKHR(
     VkInstance instance, const VkWin32SurfaceCreateInfoKHR *pCreateInfo,
     const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
+    VkResult vkRes = VK_SUCCESS;
     // First, check to ensure the appropriate extension was enabled:
     struct loader_instance *ptr_instance = loader_get_instance(instance);
     if (!ptr_instance->wsi_win32_surface_enabled) {
         loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
                    "VK_KHR_win32_surface extension not enabled.  "
                    "vkCreateWin32SurfaceKHR not executed!\n");
-        return VK_ERROR_EXTENSION_NOT_PRESENT;
+        vkRes = VK_ERROR_EXTENSION_NOT_PRESENT;
+        goto out;
     }
 
     // Next, if so, proceed with the implementation of this function:
-    VkIcdSurfaceWin32 *pIcdSurface = NULL;
-
-    pIcdSurface =
-        loader_instance_heap_alloc(ptr_instance, sizeof(VkIcdSurfaceWin32),
-                                   VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+    VkIcdSurface *pIcdSurface = loader_instance_heap_alloc(
+        ptr_instance, sizeof(VkIcdSurface), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
     if (pIcdSurface == NULL) {
-        return VK_ERROR_OUT_OF_HOST_MEMORY;
+        vkRes = VK_ERROR_OUT_OF_HOST_MEMORY;
+        goto out;
     }
 
-    pIcdSurface->base.platform = VK_ICD_WSI_PLATFORM_WIN32;
-    pIcdSurface->hinstance = pCreateInfo->hinstance;
-    pIcdSurface->hwnd = pCreateInfo->hwnd;
+    pIcdSurface->win_surf.base.platform = VK_ICD_WSI_PLATFORM_WIN32;
+    pIcdSurface->win_surf.hinstance = pCreateInfo->hinstance;
+    pIcdSurface->win_surf.hwnd = pCreateInfo->hwnd;
+
+    // Setup the new sizes and offsets so we can grow the structures in the
+    // future withouth having problems
+    pIcdSurface->base_size = sizeof(pIcdSurface->win_surf.base);
+    pIcdSurface->platform_size = sizeof(pIcdSurface->win_surf);
+    pIcdSurface->non_platform_offset = (uint32_t)(
+        (uint8_t *)(&pIcdSurface->base_size) - (uint8_t *)pIcdSurface);
+    pIcdSurface->entire_size = sizeof(VkIcdSurface);
+
+    pIcdSurface->real_icd_surfaces = loader_instance_heap_alloc(
+        ptr_instance, sizeof(VkSurfaceKHR) * ptr_instance->total_icd_count,
+        VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+    if (pIcdSurface == NULL) {
+        vkRes = VK_ERROR_OUT_OF_HOST_MEMORY;
+        goto out;
+    }
+    memset(pIcdSurface->real_icd_surfaces, 0,
+           sizeof(VkSurfaceKHR) * ptr_instance->total_icd_count);
+
+    // Loop through each ICD and determine if they need to create a surface
+    for (uint32_t i = 0; i < ptr_instance->total_icd_count; i++) {
+        if (ptr_instance->icd_libs.list[i].interface_version >=
+            ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
+            struct loader_icd *icd = &ptr_instance->icds[i];
+            if (NULL != icd->CreateWin32SurfaceKHR) {
+                vkRes = icd->CreateWin32SurfaceKHR(
+                    instance, pCreateInfo, pAllocator,
+                    &pIcdSurface->real_icd_surfaces[i]);
+                if (VK_SUCCESS != vkRes) {
+                    goto out;
+                }
+            }
+        }
+    }
 
-    *pSurface = (VkSurfaceKHR)pIcdSurface;
+    *pSurface = (VkSurfaceKHR)(pIcdSurface);
+
+out:
+
+    if (VK_SUCCESS != vkRes && NULL != pIcdSurface) {
+        if (NULL != pIcdSurface->real_icd_surfaces) {
+            for (uint32_t i = 0; i < ptr_instance->total_icd_count; i++) {
+                struct loader_icd *icd = &ptr_instance->icds[i];
+                if (NULL != pIcdSurface->real_icd_surfaces[i] &&
+                    NULL != icd->DestroySurfaceKHR) {
+                    icd->DestroySurfaceKHR(
+                        instance, pIcdSurface->real_icd_surfaces[i], pAllocator);
+                }
+            }
+            loader_instance_heap_free(ptr_instance, pIcdSurface->real_icd_surfaces);
+        }
+        loader_instance_heap_free(ptr_instance, pIcdSurface);
+    }
 
-    return VK_SUCCESS;
+    return vkRes;
 }
 
 // This is the trampoline entrypoint for
@@ -561,32 +727,83 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateMirSurfaceKHR(
 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateMirSurfaceKHR(
     VkInstance instance, const VkMirSurfaceCreateInfoKHR *pCreateInfo,
     const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
+    VkResult vkRes = VK_SUCCESS;
     // First, check to ensure the appropriate extension was enabled:
     struct loader_instance *ptr_instance = loader_get_instance(instance);
     if (!ptr_instance->wsi_mir_surface_enabled) {
         loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
                    "VK_KHR_mir_surface extension not enabled.  "
                    "vkCreateMirSurfaceKHR not executed!\n");
-        return VK_ERROR_EXTENSION_NOT_PRESENT;
+        vkRes = VK_ERROR_EXTENSION_NOT_PRESENT;
+        goto out;
     }
 
     // Next, if so, proceed with the implementation of this function:
-    VkIcdSurfaceMir *pIcdSurface = NULL;
-
-    pIcdSurface =
-        loader_instance_heap_alloc(ptr_instance, sizeof(VkIcdSurfaceMir),
-                                   VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+    VkIcdSurface *pIcdSurface = loader_instance_heap_alloc(
+        ptr_instance, sizeof(VkIcdSurface), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
     if (pIcdSurface == NULL) {
-        return VK_ERROR_OUT_OF_HOST_MEMORY;
+        vkRes = VK_ERROR_OUT_OF_HOST_MEMORY;
+        goto out;
     }
 
-    pIcdSurface->base.platform = VK_ICD_WSI_PLATFORM_MIR;
-    pIcdSurface->connection = pCreateInfo->connection;
-    pIcdSurface->mirSurface = pCreateInfo->mirSurface;
+    pIcdSurface->mir_surf.base.platform = VK_ICD_WSI_PLATFORM_MIR;
+    pIcdSurface->mir_surf.connection = pCreateInfo->connection;
+    pIcdSurface->mir_surf.mirSurface = pCreateInfo->mirSurface;
+
+    // Setup the new sizes and offsets so we can grow the structures in the
+    // future withouth having problems
+    pIcdSurface->base_size = sizeof(pIcdSurface->mir_surf.base);
+    pIcdSurface->platform_size = sizeof(pIcdSurface->mir_surf);
+    pIcdSurface->non_platform_offset = (uint32_t)(
+        (uint8_t *)(&pIcdSurface->base_size) - (uint8_t *)pIcdSurface);
+    pIcdSurface->entire_size = sizeof(VkIcdSurface);
+
+    pIcdSurface->real_icd_surfaces = loader_instance_heap_alloc(
+        ptr_instance, sizeof(VkSurfaceKHR) * ptr_instance->total_icd_count,
+        VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+    if (pIcdSurface == NULL) {
+        vkRes = VK_ERROR_OUT_OF_HOST_MEMORY;
+        goto out;
+    }
+    memset(pIcdSurface->real_icd_surfaces, 0,
+           sizeof(VkSurfaceKHR) * ptr_instance->total_icd_count);
+
+    // Loop through each ICD and determine if they need to create a surface
+    for (uint32_t i = 0; i < ptr_instance->total_icd_count; i++) {
+        if (ptr_instance->icd_libs.list[i].interface_version >=
+            ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
+            struct loader_icd *icd = &ptr_instance->icds[i];
+            if (NULL != icd->CreateMirSurfaceKHR) {
+                vkRes = icd->CreateMirSurfaceKHR(
+                    instance, pCreateInfo, pAllocator,
+                    &pIcdSurface->real_icd_surfaces[i]);
+                if (VK_SUCCESS != vkRes) {
+                    goto out;
+                }
+            }
+        }
+    }
 
     *pSurface = (VkSurfaceKHR)pIcdSurface;
 
-    return VK_SUCCESS;
+out:
+
+    if (VK_SUCCESS != vkRes && NULL != pIcdSurface) {
+        if (NULL != pIcdSurface->real_icd_surfaces) {
+            for (uint32_t i = 0; i < ptr_instance->total_icd_count; i++) {
+                struct loader_icd *icd = &ptr_instance->icds[i];
+                if (NULL != pIcdSurface->real_icd_surfaces[i] &&
+                    NULL != icd->DestroySurfaceKHR) {
+                    icd->DestroySurfaceKHR(
+                        instance, pIcdSurface->real_icd_surfaces[i], pAllocator);
+                }
+            }
+            loader_instance_heap_free(ptr_instance, pIcdSurface->real_icd_surfaces);
+        }
+        loader_instance_heap_free(ptr_instance, pIcdSurface);
+    }
+
+    return vkRes;
 }
 
 // This is the trampoline entrypoint for
@@ -637,15 +854,13 @@ terminator_GetPhysicalDeviceMirPresentationSupportKHR(
 
 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
 
-
-// Functions for the VK_KHR_wayland_surface extension:
-
-// This is the trampoline entrypoint for CreateWaylandSurfaceKHR
-LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkCreateWaylandSurfaceKHR(VkInstance instance,
-                          const VkWaylandSurfaceCreateInfoKHR *pCreateInfo,
-                          const VkAllocationCallbacks *pAllocator,
-                          VkSurfaceKHR *pSurface) {
+/*
+ * This is the trampoline entrypoint
+ * for CreateWaylandSurfaceKHR
+ */
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateWaylandSurfaceKHR(
+    VkInstance instance, const VkWaylandSurfaceCreateInfoKHR *pCreateInfo,
+    const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
     const VkLayerInstanceDispatchTable *disp;
     disp = loader_get_instance_dispatch(instance);
     VkResult res;
@@ -659,32 +874,83 @@ vkCreateWaylandSurfaceKHR(VkInstance instance,
 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateWaylandSurfaceKHR(
     VkInstance instance, const VkWaylandSurfaceCreateInfoKHR *pCreateInfo,
     const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
+    VkResult vkRes = VK_SUCCESS;
     // First, check to ensure the appropriate extension was enabled:
     struct loader_instance *ptr_instance = loader_get_instance(instance);
     if (!ptr_instance->wsi_wayland_surface_enabled) {
         loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
                    "VK_KHR_wayland_surface extension not enabled.  "
                    "vkCreateWaylandSurfaceKHR not executed!\n");
-        return VK_ERROR_EXTENSION_NOT_PRESENT;
+        vkRes = VK_ERROR_EXTENSION_NOT_PRESENT;
+        goto out;
     }
 
     // Next, if so, proceed with the implementation of this function:
-    VkIcdSurfaceWayland *pIcdSurface = NULL;
-
-    pIcdSurface =
-        loader_instance_heap_alloc(ptr_instance, sizeof(VkIcdSurfaceWayland),
-                                   VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+    VkIcdSurface *pIcdSurface = loader_instance_heap_alloc(
+        ptr_instance, sizeof(VkIcdSurface), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
     if (pIcdSurface == NULL) {
-        return VK_ERROR_OUT_OF_HOST_MEMORY;
+        vkRes = VK_ERROR_OUT_OF_HOST_MEMORY;
+        goto out;
     }
 
-    pIcdSurface->base.platform = VK_ICD_WSI_PLATFORM_WAYLAND;
-    pIcdSurface->display = pCreateInfo->display;
-    pIcdSurface->surface = pCreateInfo->surface;
+    pIcdSurface->wayland_surf.base.platform = VK_ICD_WSI_PLATFORM_WAYLAND;
+    pIcdSurface->wayland_surf.display = pCreateInfo->display;
+    pIcdSurface->wayland_surf.surface = pCreateInfo->surface;
+
+    // Setup the new sizes and offsets so we can grow the structures in the
+    // future withouth having problems
+    pIcdSurface->base_size = sizeof(pIcdSurface->wayland_surf.base);
+    pIcdSurface->platform_size = sizeof(pIcdSurface->wayland_surf);
+    pIcdSurface->non_platform_offset = (uint32_t)(
+        (uint8_t *)(&pIcdSurface->base_size) - (uint8_t *)pIcdSurface);
+    pIcdSurface->entire_size = sizeof(VkIcdSurface);
+
+    pIcdSurface->real_icd_surfaces = loader_instance_heap_alloc(
+        ptr_instance, sizeof(VkSurfaceKHR) * ptr_instance->total_icd_count,
+        VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+    if (pIcdSurface == NULL) {
+        vkRes = VK_ERROR_OUT_OF_HOST_MEMORY;
+        goto out;
+    }
+    memset(pIcdSurface->real_icd_surfaces, 0,
+           sizeof(VkSurfaceKHR) * ptr_instance->total_icd_count);
+
+    // Loop through each ICD and determine if they need to create a surface
+    for (uint32_t i = 0; i < ptr_instance->total_icd_count; i++) {
+        if (ptr_instance->icd_libs.list[i].interface_version >=
+            ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
+            struct loader_icd *icd = &ptr_instance->icds[i];
+            if (NULL != icd->CreateWaylandSurfaceKHR) {
+                vkRes = icd->CreateWaylandSurfaceKHR(
+                    instance, pCreateInfo, pAllocator,
+                    &pIcdSurface->real_icd_surfaces[i]);
+                if (VK_SUCCESS != vkRes) {
+                    goto out;
+                }
+            }
+        }
+    }
 
     *pSurface = (VkSurfaceKHR)pIcdSurface;
 
-    return VK_SUCCESS;
+out:
+
+    if (VK_SUCCESS != vkRes && NULL != pIcdSurface) {
+        if (NULL != pIcdSurface->real_icd_surfaces) {
+            for (uint32_t i = 0; i < ptr_instance->total_icd_count; i++) {
+                struct loader_icd *icd = &ptr_instance->icds[i];
+                if (NULL != pIcdSurface->real_icd_surfaces[i] &&
+                    NULL != icd->DestroySurfaceKHR) {
+                    icd->DestroySurfaceKHR(
+                        instance, pIcdSurface->real_icd_surfaces[i], pAllocator);
+                }
+            }
+            loader_instance_heap_free(ptr_instance, pIcdSurface->real_icd_surfaces);
+        }
+        loader_instance_heap_free(ptr_instance, pIcdSurface);
+    }
+
+    return vkRes;
 }
 
 
@@ -756,32 +1022,83 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateXcbSurfaceKHR(
 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateXcbSurfaceKHR(
     VkInstance instance, const VkXcbSurfaceCreateInfoKHR *pCreateInfo,
     const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
+    VkResult vkRes = VK_SUCCESS;
     // First, check to ensure the appropriate extension was enabled:
     struct loader_instance *ptr_instance = loader_get_instance(instance);
     if (!ptr_instance->wsi_xcb_surface_enabled) {
         loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
                    "VK_KHR_xcb_surface extension not enabled.  "
                    "vkCreateXcbSurfaceKHR not executed!\n");
-        return VK_ERROR_EXTENSION_NOT_PRESENT;
+        vkRes = VK_ERROR_EXTENSION_NOT_PRESENT;
+        goto out;
     }
 
     // Next, if so, proceed with the implementation of this function:
-    VkIcdSurfaceXcb *pIcdSurface = NULL;
-
-    pIcdSurface =
-        loader_instance_heap_alloc(ptr_instance, sizeof(VkIcdSurfaceXcb),
-                                   VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+    VkIcdSurface *pIcdSurface = loader_instance_heap_alloc(
+        ptr_instance, sizeof(VkIcdSurface), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
     if (pIcdSurface == NULL) {
-        return VK_ERROR_OUT_OF_HOST_MEMORY;
+        vkRes = VK_ERROR_OUT_OF_HOST_MEMORY;
+        goto out;
     }
 
-    pIcdSurface->base.platform = VK_ICD_WSI_PLATFORM_XCB;
-    pIcdSurface->connection = pCreateInfo->connection;
-    pIcdSurface->window = pCreateInfo->window;
+    pIcdSurface->xcb_surf.base.platform = VK_ICD_WSI_PLATFORM_XCB;
+    pIcdSurface->xcb_surf.connection = pCreateInfo->connection;
+    pIcdSurface->xcb_surf.window = pCreateInfo->window;
+
+    // Setup the new sizes and offsets so we can grow the structures in the
+    // future withouth having problems
+    pIcdSurface->base_size = sizeof(pIcdSurface->xcb_surf.base);
+    pIcdSurface->platform_size = sizeof(pIcdSurface->xcb_surf);
+    pIcdSurface->non_platform_offset = (uint32_t)(
+        (uint8_t *)(&pIcdSurface->base_size) - (uint8_t *)pIcdSurface);
+    pIcdSurface->entire_size = sizeof(VkIcdSurface);
+
+    pIcdSurface->real_icd_surfaces = loader_instance_heap_alloc(
+        ptr_instance, sizeof(VkSurfaceKHR) * ptr_instance->total_icd_count,
+        VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+    if (pIcdSurface == NULL) {
+        vkRes = VK_ERROR_OUT_OF_HOST_MEMORY;
+        goto out;
+    }
+    memset(pIcdSurface->real_icd_surfaces, 0,
+           sizeof(VkSurfaceKHR) * ptr_instance->total_icd_count);
+
+    // Loop through each ICD and determine if they need to create a surface
+    for (uint32_t i = 0; i < ptr_instance->total_icd_count; i++) {
+        if (ptr_instance->icd_libs.list[i].interface_version >=
+            ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
+            struct loader_icd *icd = &ptr_instance->icds[i];
+            if (NULL != icd->CreateXcbSurfaceKHR) {
+                vkRes = icd->CreateXcbSurfaceKHR(
+                    instance, pCreateInfo, pAllocator,
+                    &pIcdSurface->real_icd_surfaces[i]);
+                if (VK_SUCCESS != vkRes) {
+                    goto out;
+                }
+            }
+        }
+    }
 
     *pSurface = (VkSurfaceKHR)pIcdSurface;
 
-    return VK_SUCCESS;
+out:
+
+    if (VK_SUCCESS != vkRes && NULL != pIcdSurface) {
+        if (NULL != pIcdSurface->real_icd_surfaces) {
+            for (uint32_t i = 0; i < ptr_instance->total_icd_count; i++) {
+                struct loader_icd *icd = &ptr_instance->icds[i];
+                if (NULL != pIcdSurface->real_icd_surfaces[i] &&
+                    NULL != icd->DestroySurfaceKHR) {
+                    icd->DestroySurfaceKHR(
+                        instance, pIcdSurface->real_icd_surfaces[i], pAllocator);
+                }
+            }
+            loader_instance_heap_free(ptr_instance, pIcdSurface->real_icd_surfaces);
+        }
+        loader_instance_heap_free(ptr_instance, pIcdSurface);
+    }
+
+    return vkRes;
 }
 
 // This is the trampoline entrypoint for
@@ -852,32 +1169,83 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateXlibSurfaceKHR(
 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateXlibSurfaceKHR(
     VkInstance instance, const VkXlibSurfaceCreateInfoKHR *pCreateInfo,
     const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
+    VkResult vkRes = VK_SUCCESS;
     // First, check to ensure the appropriate extension was enabled:
     struct loader_instance *ptr_instance = loader_get_instance(instance);
     if (!ptr_instance->wsi_xlib_surface_enabled) {
         loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
                    "VK_KHR_xlib_surface extension not enabled.  "
                    "vkCreateXlibSurfaceKHR not executed!\n");
-        return VK_ERROR_EXTENSION_NOT_PRESENT;
+        vkRes = VK_ERROR_EXTENSION_NOT_PRESENT;
+        goto out;
     }
 
     // Next, if so, proceed with the implementation of this function:
-    VkIcdSurfaceXlib *pIcdSurface = NULL;
-
-    pIcdSurface =
-        loader_instance_heap_alloc(ptr_instance, sizeof(VkIcdSurfaceXlib),
-                                   VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+    VkIcdSurface *pIcdSurface = loader_instance_heap_alloc(
+        ptr_instance, sizeof(VkIcdSurface), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
     if (pIcdSurface == NULL) {
-        return VK_ERROR_OUT_OF_HOST_MEMORY;
+        vkRes = VK_ERROR_OUT_OF_HOST_MEMORY;
+        goto out;
     }
 
-    pIcdSurface->base.platform = VK_ICD_WSI_PLATFORM_XLIB;
-    pIcdSurface->dpy = pCreateInfo->dpy;
-    pIcdSurface->window = pCreateInfo->window;
+    pIcdSurface->xlib_surf.base.platform = VK_ICD_WSI_PLATFORM_XLIB;
+    pIcdSurface->xlib_surf.dpy = pCreateInfo->dpy;
+    pIcdSurface->xlib_surf.window = pCreateInfo->window;
+
+    // Setup the new sizes and offsets so we can grow the structures in the
+    // future withouth having problems
+    pIcdSurface->base_size = sizeof(pIcdSurface->xlib_surf.base);
+    pIcdSurface->platform_size = sizeof(pIcdSurface->xlib_surf);
+    pIcdSurface->non_platform_offset = (uint32_t)(
+        (uint8_t *)(&pIcdSurface->base_size) - (uint8_t *)pIcdSurface);
+    pIcdSurface->entire_size = sizeof(VkIcdSurface);
+
+    pIcdSurface->real_icd_surfaces = loader_instance_heap_alloc(
+        ptr_instance, sizeof(VkSurfaceKHR) * ptr_instance->total_icd_count,
+        VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+    if (pIcdSurface == NULL) {
+        vkRes = VK_ERROR_OUT_OF_HOST_MEMORY;
+        goto out;
+    }
+    memset(pIcdSurface->real_icd_surfaces, 0,
+           sizeof(VkSurfaceKHR) * ptr_instance->total_icd_count);
+
+    // Loop through each ICD and determine if they need to create a surface
+    for (uint32_t i = 0; i < ptr_instance->total_icd_count; i++) {
+        if (ptr_instance->icd_libs.list[i].interface_version >=
+            ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
+            struct loader_icd *icd = &ptr_instance->icds[i];
+            if (NULL != icd->CreateXlibSurfaceKHR) {
+                vkRes = icd->CreateXlibSurfaceKHR(
+                    instance, pCreateInfo, pAllocator,
+                    &pIcdSurface->real_icd_surfaces[i]);
+                if (VK_SUCCESS != vkRes) {
+                    goto out;
+                }
+            }
+        }
+    }
 
     *pSurface = (VkSurfaceKHR)pIcdSurface;
 
-    return VK_SUCCESS;
+out:
+
+    if (VK_SUCCESS != vkRes && NULL != pIcdSurface) {
+        if (NULL != pIcdSurface->real_icd_surfaces) {
+            for (uint32_t i = 0; i < ptr_instance->total_icd_count; i++) {
+                struct loader_icd *icd = &ptr_instance->icds[i];
+                if (NULL != pIcdSurface->real_icd_surfaces[i] &&
+                    NULL != icd->DestroySurfaceKHR) {
+                    icd->DestroySurfaceKHR(
+                        instance, pIcdSurface->real_icd_surfaces[i], pAllocator);
+                }
+            }
+            loader_instance_heap_free(ptr_instance, pIcdSurface->real_icd_surfaces);
+        }
+        loader_instance_heap_free(ptr_instance, pIcdSurface);
+    }
+
+    return vkRes;
 }
 
 // This is the trampoline entrypoint for GetPhysicalDeviceXlibPresentationSupportKHR
@@ -956,11 +1324,9 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateAndroidSurfaceKHR(
     }
 
     // Next, if so, proceed with the implementation of this function:
-    VkIcdSurfaceAndroid *pIcdSurface = NULL;
-
-    pIcdSurface =
+    VkIcdSurfaceAndroid *pIcdSurface =
         loader_instance_heap_alloc(ptr_instance, sizeof(VkIcdSurfaceAndroid),
-                                   VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+                                   VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
     if (pIcdSurface == NULL) {
         return VK_ERROR_OUT_OF_HOST_MEMORY;
     }
@@ -1071,11 +1437,9 @@ vkGetDisplayPlaneSupportedDisplaysKHR(VkPhysicalDevice physicalDevice,
     return res;
 }
 
-VKAPI_ATTR VkResult VKAPI_CALL
-terminator_GetDisplayPlaneSupportedDisplaysKHR(VkPhysicalDevice physicalDevice,
-                                               uint32_t planeIndex,
-                                               uint32_t *pDisplayCount,
-                                               VkDisplayKHR *pDisplays) {
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDisplayPlaneSupportedDisplaysKHR(
+    VkPhysicalDevice physicalDevice, uint32_t planeIndex,
+    uint32_t *pDisplayCount, VkDisplayKHR *pDisplays) {
     // First, check to ensure the appropriate extension was enabled:
     struct loader_physical_device *phys_dev =
         (struct loader_physical_device *)physicalDevice;
@@ -1098,10 +1462,9 @@ terminator_GetDisplayPlaneSupportedDisplaysKHR(VkPhysicalDevice physicalDevice,
         phys_dev->phys_dev, planeIndex, pDisplayCount, pDisplays);
 }
 
-LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkGetDisplayModePropertiesKHR(VkPhysicalDevice physicalDevice,
-                              VkDisplayKHR display, uint32_t *pPropertyCount,
-                              VkDisplayModePropertiesKHR *pProperties) {
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayModePropertiesKHR(
+    VkPhysicalDevice physicalDevice, VkDisplayKHR display,
+    uint32_t *pPropertyCount, VkDisplayModePropertiesKHR *pProperties) {
     VkPhysicalDevice unwrapped_phys_dev =
         loader_unwrap_physical_device(physicalDevice);
     const VkLayerInstanceDispatchTable *disp;
@@ -1175,10 +1538,9 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDisplayModeKHR(
                                      pAllocator, pMode);
 }
 
-LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkGetDisplayPlaneCapabilitiesKHR(VkPhysicalDevice physicalDevice,
-                                 VkDisplayModeKHR mode, uint32_t planeIndex,
-                                 VkDisplayPlaneCapabilitiesKHR *pCapabilities) {
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneCapabilitiesKHR(
+    VkPhysicalDevice physicalDevice, VkDisplayModeKHR mode, uint32_t planeIndex,
+    VkDisplayPlaneCapabilitiesKHR *pCapabilities) {
     VkPhysicalDevice unwrapped_phys_dev =
         loader_unwrap_physical_device(physicalDevice);
     const VkLayerInstanceDispatchTable *disp;
@@ -1229,7 +1591,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDisplayPlaneSurfaceKHR(
     VkInstance instance, const VkDisplaySurfaceCreateInfoKHR *pCreateInfo,
     const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
     struct loader_instance *inst = loader_get_instance(instance);
-    VkIcdSurfaceDisplay *pIcdSurface = NULL;
+    VkIcdSurface *pIcdSurface = NULL;
 
     if (!inst->wsi_surface_enabled) {
         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
@@ -1238,20 +1600,29 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDisplayPlaneSurfaceKHR(
         return VK_ERROR_EXTENSION_NOT_PRESENT;
     }
 
-    pIcdSurface = loader_instance_heap_alloc(
-        inst, sizeof(VkIcdSurfaceDisplay), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+    pIcdSurface = loader_instance_heap_alloc(inst, sizeof(VkIcdSurface),
+                                             VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
     if (pIcdSurface == NULL) {
         return VK_ERROR_OUT_OF_HOST_MEMORY;
     }
 
-    pIcdSurface->base.platform = VK_ICD_WSI_PLATFORM_DISPLAY;
-    pIcdSurface->displayMode = pCreateInfo->displayMode;
-    pIcdSurface->planeIndex = pCreateInfo->planeIndex;
-    pIcdSurface->planeStackIndex = pCreateInfo->planeStackIndex;
-    pIcdSurface->transform = pCreateInfo->transform;
-    pIcdSurface->globalAlpha = pCreateInfo->globalAlpha;
-    pIcdSurface->alphaMode = pCreateInfo->alphaMode;
-    pIcdSurface->imageExtent = pCreateInfo->imageExtent;
+    pIcdSurface->display_surf.base.platform = VK_ICD_WSI_PLATFORM_DISPLAY;
+    pIcdSurface->display_surf.displayMode = pCreateInfo->displayMode;
+    pIcdSurface->display_surf.planeIndex = pCreateInfo->planeIndex;
+    pIcdSurface->display_surf.planeStackIndex = pCreateInfo->planeStackIndex;
+    pIcdSurface->display_surf.transform = pCreateInfo->transform;
+    pIcdSurface->display_surf.globalAlpha = pCreateInfo->globalAlpha;
+    pIcdSurface->display_surf.alphaMode = pCreateInfo->alphaMode;
+    pIcdSurface->display_surf.imageExtent = pCreateInfo->imageExtent;
+
+    // Setup the new sizes and offsets so we can grow the structures in the
+    // future withouth having problems
+    pIcdSurface->real_icd_surfaces = NULL;
+    pIcdSurface->base_size = sizeof(pIcdSurface->display_surf.base);
+    pIcdSurface->platform_size = sizeof(pIcdSurface->display_surf);
+    pIcdSurface->non_platform_offset = (uint32_t)(
+        (uint8_t *)(&pIcdSurface->base_size) - (uint8_t *)pIcdSurface);
+    pIcdSurface->entire_size = sizeof(VkIcdSurface);
 
     *pSurface = (VkSurfaceKHR)pIcdSurface;
 
index fa60088..65b3986 100644 (file)
@@ -29,6 +29,10 @@ void wsi_create_instance(struct loader_instance *ptr_instance,
                          const VkInstanceCreateInfo *pCreateInfo);
 bool wsi_unsupported_instance_extension(const VkExtensionProperties *ext_prop);
 
+VKAPI_ATTR VkResult VKAPI_CALL terminator_vkCreateSwapchainKHR(
+    VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo,
+    const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchain);
+
 VKAPI_ATTR void VKAPI_CALL
 terminator_DestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface,
                              const VkAllocationCallbacks *pAllocator);