Refactor instance level objects to not use icd_index
authorCharles Giessen <charles@lunarg.com>
Tue, 26 Mar 2024 22:23:13 +0000 (17:23 -0500)
committerCharles Giessen <46324611+charles-lunarg@users.noreply.github.com>
Mon, 29 Apr 2024 16:53:33 +0000 (10:53 -0600)
The previous way per-ICD instance level objects were accessed was
using the ICD's index into an array that was allocated with the object.
This solution worked while the indexes were static, but with the
recent change to remove unused ICD's that is no longer the case.

This commit replaces an array per object with object arrays, one for each
type (surface, debug messenger, & debug report) and per ICD. That flips
where the index comes from, with the instance storing an array indication
which indices are used and which are free.

Whenever an instance level object is created, the loader checks if there
is a free index available, reusing it if available. Otherwise it resizes
its own store as well as each ICD's array for that object.

12 files changed:
loader/debug_utils.c
loader/extension_manual.c
loader/generated/vk_loader_extensions.c
loader/loader.c
loader/loader.h
loader/loader_common.h
loader/loader_linux.c
loader/loader_windows.c
loader/trampoline.c
loader/wsi.c
loader/wsi.h
scripts/loader_extension_generator.py

index 6656eb77c330c7e9b41618054e883e186c5593ca..8a12d4a00eff924a9ea50f8459c0525bb1c4549a 100644 (file)
@@ -92,7 +92,6 @@ VkBool32 util_SubmitDebugUtilsMessageEXT(const struct loader_instance *inst, VkD
         if (0 < pCallbackData->objectCount) {
             debug_utils_AnnotObjectToDebugReportObject(pCallbackData->pObjects, &object_type, &object_handle);
         }
-
         while (pTrav) {
             if (pTrav->is_messenger && (pTrav->messenger.messageSeverity & messageSeverity) &&
                 (pTrav->messenger.messageType & messageTypes)) {
@@ -106,7 +105,6 @@ VkBool32 util_SubmitDebugUtilsMessageEXT(const struct loader_instance *inst, VkD
                     bail = true;
                 }
             }
-
             pTrav = pTrav->pNext;
         }
     }
@@ -175,33 +173,44 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugUtilsMessengerEXT(VkInstanc
                                                                        const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
                                                                        const VkAllocationCallbacks *pAllocator,
                                                                        VkDebugUtilsMessengerEXT *pMessenger) {
-    VkDebugUtilsMessengerEXT *icd_info = NULL;
-    const struct loader_icd_term *icd_term;
     struct loader_instance *inst = (struct loader_instance *)instance;
     VkResult res = VK_SUCCESS;
-    uint32_t storage_idx;
     VkLayerDbgFunctionNode *new_dbg_func_node = NULL;
+    uint32_t next_index = 0;
 
-    icd_info = (VkDebugUtilsMessengerEXT *)loader_calloc_with_instance_fallback(
-        pAllocator, inst, inst->icd_terms_count * sizeof(VkDebugUtilsMessengerEXT), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
-
-    if (!icd_info) {
+    uint32_t *pNextIndex = loader_instance_heap_alloc(inst, sizeof(uint32_t), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+    if (NULL == pNextIndex) {
         res = VK_ERROR_OUT_OF_HOST_MEMORY;
         goto out;
     }
 
-    storage_idx = 0;
-    for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
-        if (!icd_term->dispatch.CreateDebugUtilsMessengerEXT) {
-            continue;
+    res = loader_get_next_available_entry(inst, &inst->debug_utils_messengers_list, &next_index);
+    if (res != VK_SUCCESS) {
+        goto out;
+    }
+
+    for (struct loader_icd_term *icd_term = inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
+        if (icd_term->debug_utils_messenger_list.list == NULL) {
+            res = loader_init_generic_list(inst, (struct loader_generic_list *)&icd_term->debug_utils_messenger_list,
+                                           sizeof(VkDebugUtilsMessengerEXT));
+            if (res != VK_SUCCESS) {
+                goto out;
+            }
+        } else if (icd_term->debug_utils_messenger_list.capacity <= next_index * sizeof(VkDebugUtilsMessengerEXT)) {
+            res = loader_resize_generic_list(inst, (struct loader_generic_list *)&icd_term->debug_utils_messenger_list);
+            if (res != VK_SUCCESS) {
+                goto out;
+            }
         }
 
-        res = icd_term->dispatch.CreateDebugUtilsMessengerEXT(icd_term->instance, pCreateInfo, pAllocator, &icd_info[storage_idx]);
+        if (icd_term->dispatch.CreateDebugUtilsMessengerEXT) {
+            res = icd_term->dispatch.CreateDebugUtilsMessengerEXT(icd_term->instance, pCreateInfo, pAllocator,
+                                                                  &icd_term->debug_utils_messenger_list.list[next_index]);
 
-        if (res != VK_SUCCESS) {
-            goto out;
+            if (res != VK_SUCCESS) {
+                goto out;
+            }
         }
-        storage_idx++;
     }
 
     // Setup the debug report callback in the terminator since a layer may want
@@ -221,27 +230,29 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugUtilsMessengerEXT(VkInstanc
     new_dbg_func_node->pUserData = pCreateInfo->pUserData;
     new_dbg_func_node->pNext = inst->current_dbg_function_head;
     inst->current_dbg_function_head = new_dbg_func_node;
-
-    *pMessenger = (VkDebugUtilsMessengerEXT)(uintptr_t)icd_info;
+    *pNextIndex = next_index;
+    *pMessenger = (VkDebugUtilsMessengerEXT)(uintptr_t)pNextIndex;
     new_dbg_func_node->messenger.messenger = *pMessenger;
 
 out:
 
     // Roll back on errors
     if (VK_SUCCESS != res) {
-        storage_idx = 0;
-        for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
-            if (NULL == icd_term->dispatch.DestroyDebugUtilsMessengerEXT) {
-                continue;
-            }
-
-            if (icd_info && icd_info[storage_idx]) {
-                icd_term->dispatch.DestroyDebugUtilsMessengerEXT(icd_term->instance, icd_info[storage_idx], pAllocator);
+        if (pNextIndex) {
+            for (struct loader_icd_term *icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
+                if (icd_term->debug_utils_messenger_list.list && icd_term->debug_utils_messenger_list.list[next_index] &&
+                    NULL != icd_term->dispatch.DestroyDebugUtilsMessengerEXT) {
+                    icd_term->dispatch.DestroyDebugUtilsMessengerEXT(
+                        icd_term->instance, icd_term->debug_utils_messenger_list.list[next_index], pAllocator);
+                }
             }
-            storage_idx++;
+        }
+        if (inst->debug_utils_messengers_list.list &&
+            inst->debug_utils_messengers_list.capacity > (*pNextIndex) * sizeof(VkBool32)) {
+            inst->debug_utils_messengers_list.list[*pNextIndex] = VK_FALSE;
         }
         loader_free_with_instance_fallback(pAllocator, inst, new_dbg_func_node);
-        loader_free_with_instance_fallback(pAllocator, inst, icd_info);
+        loader_free_with_instance_fallback(pAllocator, inst, pNextIndex);
     }
 
     return res;
@@ -250,27 +261,28 @@ out:
 // This is the instance chain terminator function for DestroyDebugUtilsMessenger
 VKAPI_ATTR void VKAPI_CALL terminator_DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger,
                                                                     const VkAllocationCallbacks *pAllocator) {
-    uint32_t storage_idx;
-    VkDebugUtilsMessengerEXT *icd_info;
-    const struct loader_icd_term *icd_term;
-
     struct loader_instance *inst = (struct loader_instance *)instance;
-    icd_info = (VkDebugUtilsMessengerEXT *)(uintptr_t)messenger;
-    storage_idx = 0;
-    for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
-        if (NULL == icd_term->dispatch.DestroyDebugUtilsMessengerEXT) {
-            continue;
-        }
+    uint32_t *debug_messenger_index = (uint32_t *)(uintptr_t)messenger;
+    // Make sure that messenger actually points to anything
+    if (NULL == debug_messenger_index) {
+        return;
+    }
 
-        if (icd_info && icd_info[storage_idx]) {
-            icd_term->dispatch.DestroyDebugUtilsMessengerEXT(icd_term->instance, icd_info[storage_idx], pAllocator);
+    for (struct loader_icd_term *icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
+        if (icd_term->debug_utils_messenger_list.list && icd_term->debug_utils_messenger_list.list[*debug_messenger_index] &&
+            NULL != icd_term->dispatch.DestroyDebugUtilsMessengerEXT) {
+            icd_term->dispatch.DestroyDebugUtilsMessengerEXT(
+                icd_term->instance, icd_term->debug_utils_messenger_list.list[*debug_messenger_index], pAllocator);
         }
-        storage_idx++;
     }
 
     util_DestroyDebugUtilsMessenger(inst, messenger, pAllocator);
+    if (inst->debug_utils_messengers_list.list &&
+        inst->debug_utils_messengers_list.capacity > (*debug_messenger_index) * sizeof(VkBool32)) {
+        inst->debug_utils_messengers_list.list[*debug_messenger_index] = VK_FALSE;
+    }
 
-    loader_free_with_instance_fallback(pAllocator, inst, icd_info);
+    loader_free_with_instance_fallback(pAllocator, inst, debug_messenger_index);
 }
 
 // This is the instance chain terminator function for SubmitDebugUtilsMessageEXT
@@ -431,32 +443,44 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugReportCallbackEXT(VkInstanc
                                                                        const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
                                                                        const VkAllocationCallbacks *pAllocator,
                                                                        VkDebugReportCallbackEXT *pCallback) {
-    VkDebugReportCallbackEXT *icd_info = NULL;
-    const struct loader_icd_term *icd_term;
     struct loader_instance *inst = (struct loader_instance *)instance;
     VkResult res = VK_SUCCESS;
-    uint32_t storage_idx;
     VkLayerDbgFunctionNode *new_dbg_func_node = NULL;
+    uint32_t next_index = 0;
 
-    icd_info = ((VkDebugReportCallbackEXT *)loader_calloc_with_instance_fallback(
-        pAllocator, inst, inst->icd_terms_count * sizeof(VkDebugReportCallbackEXT), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
-    if (!icd_info) {
+    uint32_t *pNextIndex = loader_instance_heap_alloc(inst, sizeof(uint32_t), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+    if (NULL == pNextIndex) {
         res = VK_ERROR_OUT_OF_HOST_MEMORY;
         goto out;
     }
 
-    storage_idx = 0;
-    for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
-        if (!icd_term->dispatch.CreateDebugReportCallbackEXT) {
-            continue;
+    res = loader_get_next_available_entry(inst, &inst->debug_report_callbacks_list, &next_index);
+    if (res != VK_SUCCESS) {
+        goto out;
+    }
+
+    for (struct loader_icd_term *icd_term = inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
+        if (icd_term->debug_report_callback_list.list == NULL) {
+            res = loader_init_generic_list(inst, (struct loader_generic_list *)&icd_term->debug_report_callback_list,
+                                           sizeof(VkDebugUtilsMessengerEXT));
+            if (res != VK_SUCCESS) {
+                goto out;
+            }
+        } else if (icd_term->debug_report_callback_list.capacity <= next_index * sizeof(VkDebugReportCallbackEXT)) {
+            res = loader_resize_generic_list(inst, (struct loader_generic_list *)&icd_term->debug_report_callback_list);
+            if (res != VK_SUCCESS) {
+                goto out;
+            }
         }
 
-        res = icd_term->dispatch.CreateDebugReportCallbackEXT(icd_term->instance, pCreateInfo, pAllocator, &icd_info[storage_idx]);
+        if (icd_term->dispatch.CreateDebugReportCallbackEXT) {
+            res = icd_term->dispatch.CreateDebugReportCallbackEXT(icd_term->instance, pCreateInfo, pAllocator,
+                                                                  &icd_term->debug_report_callback_list.list[next_index]);
 
-        if (res != VK_SUCCESS) {
-            goto out;
+            if (res != VK_SUCCESS) {
+                goto out;
+            }
         }
-        storage_idx++;
     }
 
     // Setup the debug report callback in the terminator since a layer may want
@@ -476,27 +500,29 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugReportCallbackEXT(VkInstanc
     new_dbg_func_node->pUserData = pCreateInfo->pUserData;
     new_dbg_func_node->pNext = inst->current_dbg_function_head;
     inst->current_dbg_function_head = new_dbg_func_node;
-
-    *pCallback = (VkDebugReportCallbackEXT)(uintptr_t)icd_info;
+    *pNextIndex = next_index;
+    *pCallback = (VkDebugReportCallbackEXT)(uintptr_t)pNextIndex;
     new_dbg_func_node->report.msgCallback = *pCallback;
 
 out:
 
     // Roll back on errors
     if (VK_SUCCESS != res) {
-        storage_idx = 0;
-        for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
-            if (NULL == icd_term->dispatch.DestroyDebugReportCallbackEXT) {
-                continue;
-            }
-
-            if (icd_info && icd_info[storage_idx]) {
-                icd_term->dispatch.DestroyDebugReportCallbackEXT(icd_term->instance, icd_info[storage_idx], pAllocator);
+        if (pNextIndex) {
+            for (struct loader_icd_term *icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
+                if (icd_term->debug_report_callback_list.list && icd_term->debug_report_callback_list.list[next_index] &&
+                    NULL != icd_term->dispatch.DestroyDebugReportCallbackEXT) {
+                    icd_term->dispatch.DestroyDebugReportCallbackEXT(
+                        icd_term->instance, icd_term->debug_report_callback_list.list[next_index], pAllocator);
+                }
             }
-            storage_idx++;
+        }
+        if (inst->debug_report_callbacks_list.list &&
+            inst->debug_report_callbacks_list.capacity > (*pNextIndex) * sizeof(VkBool32)) {
+            inst->debug_report_callbacks_list.list[*pNextIndex] = VK_FALSE;
         }
         loader_free_with_instance_fallback(pAllocator, inst, new_dbg_func_node);
-        loader_free_with_instance_fallback(pAllocator, inst, icd_info);
+        loader_free_with_instance_fallback(pAllocator, inst, pNextIndex);
     }
 
     return res;
@@ -505,27 +531,26 @@ out:
 // This is the instance chain terminator function for DestroyDebugReportCallback
 VKAPI_ATTR void VKAPI_CALL terminator_DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
                                                                     const VkAllocationCallbacks *pAllocator) {
-    uint32_t storage_idx;
-    VkDebugReportCallbackEXT *icd_info;
-    const struct loader_icd_term *icd_term;
-
     struct loader_instance *inst = (struct loader_instance *)instance;
-    icd_info = (VkDebugReportCallbackEXT *)(uintptr_t)callback;
-    storage_idx = 0;
-    for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
-        if (NULL == icd_term->dispatch.DestroyDebugReportCallbackEXT) {
-            continue;
-        }
-
-        if (icd_info[storage_idx]) {
-            icd_term->dispatch.DestroyDebugReportCallbackEXT(icd_term->instance, icd_info[storage_idx], pAllocator);
+    uint32_t *debug_report_index = (uint32_t *)(uintptr_t)callback;
+    // Make sure that callback actually points to anything
+    if (NULL == debug_report_index) {
+        return;
+    }
+    for (struct loader_icd_term *icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
+        if (icd_term->debug_report_callback_list.list && icd_term->debug_report_callback_list.list[*debug_report_index] &&
+            NULL != icd_term->dispatch.DestroyDebugReportCallbackEXT) {
+            icd_term->dispatch.DestroyDebugReportCallbackEXT(
+                icd_term->instance, icd_term->debug_report_callback_list.list[*debug_report_index], pAllocator);
         }
-        storage_idx++;
     }
 
     util_DestroyDebugReportCallback(inst, callback, pAllocator);
-
-    loader_free_with_instance_fallback(pAllocator, inst, icd_info);
+    if (inst->debug_report_callbacks_list.list &&
+        inst->debug_report_callbacks_list.capacity > (*debug_report_index) * sizeof(VkBool32)) {
+        inst->debug_report_callbacks_list.list[*debug_report_index] = VK_FALSE;
+    }
+    loader_free_with_instance_fallback(pAllocator, inst, debug_report_index);
 }
 
 // This is the instance chain terminator function for DebugReportMessage
index b8ed8a33eb41ad784349f7002ac9ef8606e5e1c6..ad5fe0c1d1bf007071ac215c1cba09ea8a68d33d 100644 (file)
@@ -107,12 +107,13 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceCapabilities2E
     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
 
     VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)(surface);
-    uint8_t icd_index = phys_dev_term->icd_index;
 
     // Unwrap the surface if needed
     VkSurfaceKHR unwrapped_surface = surface;
-    if (NULL != icd_surface->real_icd_surfaces && NULL != (void *)(uintptr_t)(icd_surface->real_icd_surfaces[icd_index])) {
-        unwrapped_surface = icd_surface->real_icd_surfaces[icd_index];
+    if (NULL != phys_dev_term->this_icd_term->surface_list.list &&
+        phys_dev_term->this_icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
+        phys_dev_term->this_icd_term->surface_list.list[icd_surface->surface_index]) {
+        unwrapped_surface = phys_dev_term->this_icd_term->surface_list.list[icd_surface->surface_index];
     }
 
     if (NULL != icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilities2EXT) {
@@ -275,12 +276,13 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfacePresentModes2E
         abort();
     }
     VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)(pSurfaceInfo->surface);
-    uint8_t icd_index = phys_dev_term->icd_index;
-    if (NULL != icd_surface->real_icd_surfaces && NULL != (void *)(uintptr_t)icd_surface->real_icd_surfaces[icd_index]) {
+    if (NULL != icd_term->surface_list.list &&
+        icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
+        icd_term->surface_list.list[icd_surface->surface_index]) {
         VkPhysicalDeviceSurfaceInfo2KHR surface_info_copy;
         surface_info_copy.sType = pSurfaceInfo->sType;
         surface_info_copy.pNext = pSurfaceInfo->pNext;
-        surface_info_copy.surface = icd_surface->real_icd_surfaces[icd_index];
+        surface_info_copy.surface = icd_term->surface_list.list[icd_surface->surface_index];
         return icd_term->dispatch.GetPhysicalDeviceSurfacePresentModes2EXT(phys_dev_term->phys_dev, &surface_info_copy,
                                                                            pPresentModeCount, pPresentModes);
     }
@@ -304,9 +306,8 @@ VKAPI_ATTR VkResult VKAPI_CALL GetDeviceGroupSurfacePresentModes2EXT(VkDevice de
 VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDeviceGroupSurfacePresentModes2EXT(VkDevice device,
                                                                                 const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
                                                                                 VkDeviceGroupPresentModeFlagsKHR *pModes) {
-    uint32_t icd_index = 0;
     struct loader_device *dev;
-    struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, &icd_index);
+    struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev);
     if (NULL == icd_term || NULL == dev ||
         NULL == dev->loader_dispatch.extension_terminator_dispatch.GetDeviceGroupSurfacePresentModes2EXT) {
         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
@@ -321,12 +322,14 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDeviceGroupSurfacePresentModes2EXT(
                    "[VUID-vkGetDeviceGroupSurfacePresentModes2EXT-pSurfaceInfo-parameter]");
         abort(); /* Intentionally fail so user can correct issue. */
     }
-    VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pSurfaceInfo->surface;
-    if (NULL != icd_surface->real_icd_surfaces && NULL != (void *)(uintptr_t)icd_surface->real_icd_surfaces[icd_index]) {
+    VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)(pSurfaceInfo->surface);
+    if (NULL != icd_term->surface_list.list &&
+        icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
+        icd_term->surface_list.list[icd_surface->surface_index]) {
         VkPhysicalDeviceSurfaceInfo2KHR surface_info_copy;
         surface_info_copy.sType = pSurfaceInfo->sType;
         surface_info_copy.pNext = pSurfaceInfo->pNext;
-        surface_info_copy.surface = icd_surface->real_icd_surfaces[icd_index];
+        surface_info_copy.surface = icd_term->surface_list.list[icd_surface->surface_index];
         return dev->loader_dispatch.extension_terminator_dispatch.GetDeviceGroupSurfacePresentModes2EXT(device, &surface_info_copy,
                                                                                                         pModes);
     }
index b74369c86e5b1da3b23a99dcf253c12c68e5a22a..3fa7593b575266e2b9a1eeb80531195e04acfe33 100644 (file)
@@ -40,7 +40,7 @@
 VKAPI_ATTR VkResult VKAPI_CALL vkDevExtError(VkDevice dev) {
     struct loader_device *found_dev;
     // The device going in is a trampoline device
-    struct loader_icd_term *icd_term = loader_get_icd_and_device(dev, &found_dev, NULL);
+    struct loader_icd_term *icd_term = loader_get_icd_and_device(dev, &found_dev);
 
     if (icd_term)
         loader_log(icd_term->this_instance, VULKAN_LOADER_ERROR_BIT, 0,
@@ -5075,9 +5075,8 @@ VKAPI_ATTR VkResult VKAPI_CALL DebugMarkerSetObjectTagEXT(
 VKAPI_ATTR VkResult VKAPI_CALL terminator_DebugMarkerSetObjectTagEXT(
     VkDevice                                    device,
     const VkDebugMarkerObjectTagInfoEXT*        pTagInfo) {
-    uint32_t icd_index = 0;
     struct loader_device *dev;
-    struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, &icd_index);
+    struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev);
     if (NULL == icd_term || NULL == dev) {
         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0, "DebugMarkerSetObjectTagEXT: Invalid device handle");
         abort(); /* Intentionally fail so user can correct issue. */
@@ -5092,8 +5091,9 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_DebugMarkerSetObjectTagEXT(
     } else if (pTagInfo->objectType == VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT) {
         if (NULL != dev && NULL != dev->loader_dispatch.core_dispatch.CreateSwapchainKHR) {
             VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pTagInfo->object;
-            if (NULL != icd_surface->real_icd_surfaces) {
-                local_tag_info.object = (uint64_t)icd_surface->real_icd_surfaces[icd_index];
+            if (NULL != icd_term->surface_list.list && icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR)
+                && icd_term->surface_list.list[icd_surface->surface_index]) {
+                local_tag_info.object = (uint64_t)icd_term->surface_list.list[icd_surface->surface_index];
             }
         }
     // If this is an instance we have to replace it with the proper one for the next call.
@@ -5134,9 +5134,8 @@ VKAPI_ATTR VkResult VKAPI_CALL DebugMarkerSetObjectNameEXT(
 VKAPI_ATTR VkResult VKAPI_CALL terminator_DebugMarkerSetObjectNameEXT(
     VkDevice                                    device,
     const VkDebugMarkerObjectNameInfoEXT*       pNameInfo) {
-    uint32_t icd_index = 0;
     struct loader_device *dev;
-    struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, &icd_index);
+    struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev);
     if (NULL == icd_term || NULL == dev) {
         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0, "DebugMarkerSetObjectNameEXT: Invalid device handle");
         abort(); /* Intentionally fail so user can correct issue. */
@@ -5151,8 +5150,9 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_DebugMarkerSetObjectNameEXT(
     } else if (pNameInfo->objectType == VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT) {
         if (NULL != dev && NULL != dev->loader_dispatch.core_dispatch.CreateSwapchainKHR) {
             VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pNameInfo->object;
-            if (NULL != icd_surface->real_icd_surfaces) {
-                local_name_info.object = (uint64_t)icd_surface->real_icd_surfaces[icd_index];
+            if (NULL != icd_term->surface_list.list && icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR)
+                && icd_term->surface_list.list[icd_surface->surface_index]) {
+                local_name_info.object = (uint64_t)icd_term->surface_list.list[icd_surface->surface_index];
             }
         }
     // If this is an instance we have to replace it with the proper one for the next call.
@@ -5725,9 +5725,8 @@ VKAPI_ATTR VkResult VKAPI_CALL SetDebugUtilsObjectNameEXT(
 VKAPI_ATTR VkResult VKAPI_CALL terminator_SetDebugUtilsObjectNameEXT(
     VkDevice                                    device,
     const VkDebugUtilsObjectNameInfoEXT*        pNameInfo) {
-    uint32_t icd_index = 0;
     struct loader_device *dev;
-    struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, &icd_index);
+    struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev);
     if (NULL == icd_term || NULL == dev) {
         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0, "SetDebugUtilsObjectNameEXT: Invalid device handle");
         abort(); /* Intentionally fail so user can correct issue. */
@@ -5742,8 +5741,9 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_SetDebugUtilsObjectNameEXT(
     } else if (pNameInfo->objectType == VK_OBJECT_TYPE_SURFACE_KHR) {
         if (NULL != dev && NULL != dev->loader_dispatch.core_dispatch.CreateSwapchainKHR) {
             VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pNameInfo->objectHandle;
-            if (NULL != icd_surface->real_icd_surfaces) {
-                local_name_info.objectHandle = (uint64_t)icd_surface->real_icd_surfaces[icd_index];
+            if (NULL != icd_term->surface_list.list && icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR)
+                && icd_term->surface_list.list[icd_surface->surface_index]) {
+                local_name_info.objectHandle = (uint64_t)icd_term->surface_list.list[icd_surface->surface_index];
             }
         }
     // If this is an instance we have to replace it with the proper one for the next call.
@@ -5788,9 +5788,8 @@ VKAPI_ATTR VkResult VKAPI_CALL SetDebugUtilsObjectTagEXT(
 VKAPI_ATTR VkResult VKAPI_CALL terminator_SetDebugUtilsObjectTagEXT(
     VkDevice                                    device,
     const VkDebugUtilsObjectTagInfoEXT*         pTagInfo) {
-    uint32_t icd_index = 0;
     struct loader_device *dev;
-    struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, &icd_index);
+    struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev);
     if (NULL == icd_term || NULL == dev) {
         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0, "SetDebugUtilsObjectTagEXT: Invalid device handle");
         abort(); /* Intentionally fail so user can correct issue. */
@@ -5805,8 +5804,9 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_SetDebugUtilsObjectTagEXT(
     } else if (pTagInfo->objectType == VK_OBJECT_TYPE_SURFACE_KHR) {
         if (NULL != dev && NULL != dev->loader_dispatch.core_dispatch.CreateSwapchainKHR) {
             VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pTagInfo->objectHandle;
-            if (NULL != icd_surface->real_icd_surfaces) {
-                local_tag_info.objectHandle = (uint64_t)icd_surface->real_icd_surfaces[icd_index];
+            if (NULL != icd_term->surface_list.list && icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR)
+                && icd_term->surface_list.list[icd_surface->surface_index]) {
+                local_tag_info.objectHandle = (uint64_t)icd_term->surface_list.list[icd_surface->surface_index];
             }
         }
     // If this is an instance we have to replace it with the proper one for the next call.
index e455b48c6d3ec37880500ccc98010e59a27edf51..a2cef49f278ce836986325cdd1c5769f4f2b79c2 100644 (file)
@@ -209,7 +209,7 @@ VKAPI_ATTR VkResult VKAPI_CALL vkSetInstanceDispatch(VkInstance instance, void *
 
 VKAPI_ATTR VkResult VKAPI_CALL vkSetDeviceDispatch(VkDevice device, void *object) {
     struct loader_device *dev;
-    struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, NULL);
+    struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev);
 
     if (NULL == icd_term || NULL == dev) {
         return VK_ERROR_INITIALIZATION_FAILED;
@@ -714,11 +714,58 @@ VkResult loader_init_generic_list(const struct loader_instance *inst, struct loa
     return VK_SUCCESS;
 }
 
+VkResult loader_resize_generic_list(const struct loader_instance *inst, struct loader_generic_list *list_info) {
+    list_info->list = loader_instance_heap_realloc(inst, list_info->list, list_info->capacity, list_info->capacity * 2,
+                                                   VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+    if (list_info->list == NULL) {
+        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_resize_generic_list: Failed to allocate space for generic list");
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+    }
+    list_info->capacity = list_info->capacity * 2;
+    return VK_SUCCESS;
+}
+
 void loader_destroy_generic_list(const struct loader_instance *inst, struct loader_generic_list *list) {
     loader_instance_heap_free(inst, list->list);
     memset(list, 0, sizeof(struct loader_generic_list));
 }
 
+VkResult loader_get_next_available_entry(const struct loader_instance *inst, struct loader_used_object_list *list_info,
+                                         uint32_t *free_index) {
+    if (NULL == list_info->list) {
+        VkResult res = loader_init_generic_list(inst, (struct loader_generic_list *)list_info, sizeof(VkBool32));
+        if (VK_SUCCESS != res) {
+            return res;
+        }
+    }
+    for (uint32_t i = 0; i < list_info->capacity / sizeof(VkBool32); i++) {
+        if (list_info->list[i] == VK_FALSE) {
+            list_info->list[i] = VK_TRUE;
+            *free_index = i;
+            return VK_SUCCESS;
+        }
+    }
+    // No free space, must resize
+
+    size_t old_capacity = list_info->capacity;
+    VkResult res = loader_resize_generic_list(inst, (struct loader_generic_list *)list_info);
+    if (VK_SUCCESS != res) {
+        return res;
+    }
+    uint32_t new_index = (uint32_t)(old_capacity / sizeof(VkBool32));
+    // Zero out the newly allocated back half of list.
+    memset(&list_info->list[new_index], 0, old_capacity);
+    list_info->list[new_index] = VK_TRUE;
+    *free_index = new_index;
+    return VK_SUCCESS;
+}
+
+void loader_release_object_from_list(struct loader_used_object_list *list_info, uint32_t index_to_free) {
+    if (list_info->list && list_info->capacity > index_to_free * sizeof(VkBool32)) {
+        list_info->list[index_to_free] = VK_FALSE;
+    }
+}
+
 // Append non-duplicate extension properties defined in props to the given ext_list.
 // Return - Vk_SUCCESS on success
 VkResult loader_add_to_ext_list(const struct loader_instance *inst, struct loader_extension_list *ext_list,
@@ -1228,7 +1275,7 @@ out:
     return res;
 }
 
-struct loader_icd_term *loader_get_icd_and_device(const void *device, struct loader_device **found_dev, uint32_t *icd_index) {
+struct loader_icd_term *loader_get_icd_and_device(const void *device, struct loader_device **found_dev) {
     VkLayerDispatchTable *dispatch_table_device = loader_get_dispatch(device);
     if (NULL == dispatch_table_device) {
         *found_dev = NULL;
@@ -1238,21 +1285,16 @@ struct loader_icd_term *loader_get_icd_and_device(const void *device, struct loa
     *found_dev = NULL;
 
     for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
-        uint32_t index = 0;
         for (struct loader_icd_term *icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
             for (struct loader_device *dev = icd_term->logical_device_list; dev; dev = dev->next) {
                 // Value comparison of device prevents object wrapping by layers
                 if (loader_get_dispatch(dev->icd_device) == dispatch_table_device ||
                     (dev->chain_device != VK_NULL_HANDLE && loader_get_dispatch(dev->chain_device) == dispatch_table_device)) {
                     *found_dev = dev;
-                    if (NULL != icd_index) {
-                        *icd_index = index;
-                    }
                     loader_platform_thread_unlock_mutex(&loader_global_instance_list_lock);
                     return icd_term;
                 }
             }
-            index++;
         }
     }
     loader_platform_thread_unlock_mutex(&loader_global_instance_list_lock);
@@ -1318,6 +1360,37 @@ void loader_icd_destroy(struct loader_instance *ptr_inst, struct loader_icd_term
         dev = next_dev;
     }
 
+    for (uint32_t i = 0; i < icd_term->surface_list.capacity / sizeof(VkSurfaceKHR); i++) {
+        if (ptr_inst->surfaces_list.capacity > i * sizeof(VkBool32) && ptr_inst->surfaces_list.list[i] == VK_TRUE &&
+            NULL != icd_term->surface_list.list && icd_term->surface_list.list[i] && NULL != icd_term->dispatch.DestroySurfaceKHR) {
+            icd_term->dispatch.DestroySurfaceKHR(icd_term->instance, icd_term->surface_list.list[i], pAllocator);
+            icd_term->surface_list.list[i] = (VkSurfaceKHR)(uintptr_t)NULL;
+        }
+    }
+    loader_destroy_generic_list(ptr_inst, (struct loader_generic_list *)&icd_term->surface_list);
+
+    for (uint32_t i = 0; i < icd_term->debug_utils_messenger_list.capacity / sizeof(VkDebugUtilsMessengerEXT); i++) {
+        if (ptr_inst->debug_utils_messengers_list.capacity > i * sizeof(VkBool32) &&
+            ptr_inst->debug_utils_messengers_list.list[i] == VK_TRUE && NULL != icd_term->debug_utils_messenger_list.list &&
+            icd_term->debug_utils_messenger_list.list[i] && NULL != icd_term->dispatch.DestroyDebugUtilsMessengerEXT) {
+            icd_term->dispatch.DestroyDebugUtilsMessengerEXT(icd_term->instance, icd_term->debug_utils_messenger_list.list[i],
+                                                             pAllocator);
+            icd_term->debug_utils_messenger_list.list[i] = (VkDebugUtilsMessengerEXT)(uintptr_t)NULL;
+        }
+    }
+    loader_destroy_generic_list(ptr_inst, (struct loader_generic_list *)&icd_term->debug_utils_messenger_list);
+
+    for (uint32_t i = 0; i < icd_term->debug_report_callback_list.capacity / sizeof(VkDebugReportCallbackEXT); i++) {
+        if (ptr_inst->debug_report_callbacks_list.capacity > i * sizeof(VkBool32) &&
+            ptr_inst->debug_report_callbacks_list.list[i] == VK_TRUE && NULL != icd_term->debug_report_callback_list.list &&
+            icd_term->debug_report_callback_list.list[i] && NULL != icd_term->dispatch.DestroyDebugReportCallbackEXT) {
+            icd_term->dispatch.DestroyDebugReportCallbackEXT(icd_term->instance, icd_term->debug_report_callback_list.list[i],
+                                                             pAllocator);
+            icd_term->debug_report_callback_list.list[i] = (VkDebugReportCallbackEXT)(uintptr_t)NULL;
+        }
+    }
+    loader_destroy_generic_list(ptr_inst, (struct loader_generic_list *)&icd_term->debug_report_callback_list);
+
     loader_instance_heap_free(ptr_inst, icd_term);
 }
 
@@ -4065,7 +4138,7 @@ VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_gpa_instance_terminator(VkInstan
 
 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_gpa_device_terminator(VkDevice device, const char *pName) {
     struct loader_device *dev;
-    struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, NULL);
+    struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev);
 
     // Return this function if a layer above here is asking for the vkGetDeviceProcAddr.
     // This is so we can properly intercept any device commands needing a terminator.
@@ -4394,7 +4467,7 @@ VKAPI_ATTR void VKAPI_CALL loader_layer_destroy_device(VkDevice device, const Vk
         return;
     }
 
-    struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, NULL);
+    struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev);
 
     destroyFunction(device, pAllocator);
     if (NULL != dev) {
@@ -6113,7 +6186,6 @@ VkResult check_and_add_to_new_phys_devs(struct loader_instance *inst, VkPhysical
 
     loader_set_dispatch((void *)new_phys_devs[idx], inst->disp);
     new_phys_devs[idx]->this_icd_term = dev_array->icd_term;
-    new_phys_devs[idx]->icd_index = (uint8_t)(dev_array->icd_index);
     new_phys_devs[idx]->phys_dev = physical_device;
 
     // Increment the count of new physical devices
@@ -6214,7 +6286,6 @@ VkResult setup_loader_term_phys_devs(struct loader_instance *inst) {
             icd_phys_dev_array[icd_idx].physical_devices = 0;
         }
         icd_phys_dev_array[icd_idx].icd_term = icd_term;
-        icd_phys_dev_array[icd_idx].icd_index = icd_idx;
         icd_term->physical_device_count = icd_phys_dev_array[icd_idx].device_count;
         icd_term = icd_term->next;
         ++icd_idx;
@@ -6959,7 +7030,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumeratePhysicalDeviceGroups(
 
         cur_icd_group_count = 0;
         icd_term = inst->icd_terms;
-        for (uint8_t icd_idx = 0; NULL != icd_term; icd_term = icd_term->next, icd_idx++) {
+        while (NULL != icd_term) {
             uint32_t count_this_time = total_count - cur_icd_group_count;
 
             // Get the function pointer to use to call into the ICD. This could be the core or KHR version
@@ -6995,7 +7066,6 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumeratePhysicalDeviceGroups(
                 for (uint32_t indiv_gpu = 0; indiv_gpu < count_this_time; indiv_gpu++) {
                     uint32_t cur_index = indiv_gpu + cur_icd_group_count;
                     local_phys_dev_groups[cur_index].this_icd_term = icd_term;
-                    local_phys_dev_groups[cur_index].icd_index = icd_idx;
                     local_phys_dev_groups[cur_index].group_props.physicalDeviceCount = 1;
                     local_phys_dev_groups[cur_index].group_props.physicalDevices[0] = phys_dev_array[indiv_gpu];
                 }
@@ -7026,7 +7096,6 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumeratePhysicalDeviceGroups(
                         uint32_t cur_index = group + cur_icd_group_count;
                         local_phys_dev_groups[cur_index].group_props = pPhysicalDeviceGroupProperties[cur_index];
                         local_phys_dev_groups[cur_index].this_icd_term = icd_term;
-                        local_phys_dev_groups[cur_index].icd_index = icd_idx;
                     }
                 } else {
                     // There's not enough space in the callee's allocated pPhysicalDeviceGroupProperties structs,
@@ -7057,7 +7126,6 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumeratePhysicalDeviceGroups(
                         uint32_t cur_index = group + cur_icd_group_count;
                         local_phys_dev_groups[cur_index].group_props = tmp_group_props[group];
                         local_phys_dev_groups[cur_index].this_icd_term = icd_term;
-                        local_phys_dev_groups[cur_index].icd_index = icd_idx;
                     }
                 }
                 if (VK_SUCCESS != res) {
@@ -7070,6 +7138,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumeratePhysicalDeviceGroups(
             }
 
             cur_icd_group_count += count_this_time;
+            icd_term = icd_term->next;
         }
 
 #if defined(LOADER_ENABLE_LINUX_SORT)
index 6bd7115f4ce5013f9c422dfcc2441ebbd6e41dcd..7be68f97f019f55871ae335b058e1737403a91bf 100644 (file)
@@ -119,6 +119,10 @@ VkResult copy_str_to_string_list(const struct loader_instance *inst, struct load
 void free_string_list(const struct loader_instance *inst, struct loader_string_list *string_list);
 
 VkResult loader_init_generic_list(const struct loader_instance *inst, struct loader_generic_list *list_info, size_t element_size);
+VkResult loader_resize_generic_list(const struct loader_instance *inst, struct loader_generic_list *list_info);
+VkResult loader_get_next_available_entry(const struct loader_instance *inst, struct loader_used_object_list *list_info,
+                                         uint32_t *free_index);
+void loader_release_object_from_list(struct loader_used_object_list *list_info, uint32_t index_to_free);
 bool has_vk_extension_property_array(const VkExtensionProperties *vk_ext_prop, const uint32_t count,
                                      const VkExtensionProperties *ext_array);
 bool has_vk_extension_property(const VkExtensionProperties *vk_ext_prop, const struct loader_extension_list *ext_list);
@@ -161,7 +165,7 @@ VkResult loader_scan_for_implicit_layers(struct loader_instance *inst, struct lo
                                          const struct loader_envvar_all_filters *layer_filters);
 VkResult loader_get_icd_loader_instance_extensions(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list,
                                                    struct loader_extension_list *inst_exts);
-struct loader_icd_term *loader_get_icd_and_device(const void *device, struct loader_device **found_dev, uint32_t *icd_index);
+struct loader_icd_term *loader_get_icd_and_device(const void *device, struct loader_device **found_dev);
 struct loader_instance *loader_get_instance(const VkInstance instance);
 struct loader_device *loader_create_logical_device(const struct loader_instance *inst, const VkAllocationCallbacks *pAllocator);
 void loader_add_logical_device(struct loader_icd_term *icd_term, struct loader_device *found_dev);
index 53ee0f0dc340b438ab25aede46e5921f759166f9..0b76387e9702437db12b5b279620ca0c3c3902d0 100644 (file)
@@ -90,6 +90,30 @@ struct loader_device_extension_list {
     struct loader_dev_ext_props *list;
 };
 
+struct loader_used_object_list {
+    size_t capacity;
+    uint32_t padding;  // count variable isn't used
+    VkBool32 *list;
+};
+
+struct loader_surface_list {
+    size_t capacity;
+    uint32_t padding;  // count variable isn't used
+    VkSurfaceKHR *list;
+};
+
+struct loader_debug_utils_messenger_list {
+    size_t capacity;
+    uint32_t padding;  // count variable isn't used
+    VkDebugUtilsMessengerEXT *list;
+};
+
+struct loader_debug_report_callback_list {
+    size_t capacity;
+    uint32_t padding;  // count variable isn't used
+    VkDebugReportCallbackEXT *list;
+};
+
 struct loader_name_value {
     char *name;
     char *value;
@@ -231,6 +255,10 @@ struct loader_icd_term {
     bool supports_get_dev_prop_2;
 
     uint32_t physical_device_count;
+
+    struct loader_surface_list surface_list;
+    struct loader_debug_utils_messenger_list debug_utils_messenger_list;
+    struct loader_debug_report_callback_list debug_report_callback_list;
 };
 
 // Per ICD library structure
@@ -309,6 +337,11 @@ struct loader_instance {
     struct loader_extension_list ext_list;  // icds and loaders extensions
     struct loader_instance_extension_enables enabled_known_extensions;
 
+    // Indicates which indices in the array are in-use and which are free to be reused
+    struct loader_used_object_list surfaces_list;
+    struct loader_used_object_list debug_utils_messengers_list;
+    struct loader_used_object_list debug_report_callbacks_list;
+
     // Stores debug callbacks - used in the log.
     VkLayerDbgFunctionNode *current_dbg_function_head;        // Current head
     VkLayerDbgFunctionNode *instance_only_dbg_function_head;  // Only used for instance create/destroy
@@ -399,7 +432,6 @@ struct loader_physical_device_tramp {
 struct loader_physical_device_term {
     struct loader_instance_dispatch_table *disp;  // must be first entry in structure
     struct loader_icd_term *this_icd_term;
-    uint8_t icd_index;
     VkPhysicalDevice phys_dev;  // object from ICD
 };
 
@@ -413,7 +445,6 @@ struct LinuxSortedDeviceInfo {
     bool default_device;
 
     // Loader specific items about the driver providing support for this physical device
-    uint32_t icd_index;
     struct loader_icd_term *icd_term;
 
     // Some generic device properties
@@ -434,7 +465,6 @@ struct LinuxSortedDeviceInfo {
 // Per enumerated PhysicalDeviceGroup structure, used to wrap in terminator code
 struct loader_physical_device_group_term {
     struct loader_icd_term *this_icd_term;
-    uint8_t icd_index;
     VkPhysicalDeviceGroupProperties group_props;
 #if defined(LOADER_ENABLE_LINUX_SORT)
     struct LinuxSortedDeviceInfo internal_device_info[VK_MAX_DEVICE_GROUP_SIZE];
@@ -469,7 +499,6 @@ enum loader_data_files_type {
 struct loader_icd_physical_devices {
     uint32_t device_count;
     VkPhysicalDevice *physical_devices;
-    uint32_t icd_index;
     struct loader_icd_term *icd_term;
 #if defined(WIN32)
     LUID windows_adapter_luid;
index e0b3db81b20126b53e0d0b7fb279a84429b591e5..4c12be600f12dd08d4e73271eb11fe3237ff91c1 100644 (file)
@@ -256,7 +256,6 @@ VkResult linux_read_sorted_physical_devices(struct loader_instance *inst, uint32
             VkPhysicalDeviceProperties dev_props = {};
 
             sorted_device_info[index].physical_device = icd_devices[icd_idx].physical_devices[phys_dev];
-            sorted_device_info[index].icd_index = icd_idx;
             sorted_device_info[index].icd_term = icd_term;
             sorted_device_info[index].has_pci_bus_info = false;
 
@@ -330,7 +329,6 @@ VkResult linux_read_sorted_physical_devices(struct loader_instance *inst, uint32
     // Add all others after (they've already been sorted)
     for (uint32_t dev = 0; dev < phys_dev_count; ++dev) {
         sorted_device_term[dev]->this_icd_term = sorted_device_info[dev].icd_term;
-        sorted_device_term[dev]->icd_index = sorted_device_info[dev].icd_index;
         sorted_device_term[dev]->phys_dev = sorted_device_info[dev].physical_device;
         loader_set_dispatch((void *)sorted_device_term[dev], inst->disp);
         loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_DRIVER_BIT, 0, "           [%u] %s  %s", dev,
index fa245cc00035cb0b13436ba97c9f5b4dd805bb48..43ecf66720190034dd6b3a97fbf7d0cae4253f88 100644 (file)
@@ -795,8 +795,8 @@ out:
     return vk_result;
 }
 
-VkResult enumerate_adapter_physical_devices(struct loader_instance *inst, struct loader_icd_term *icd_term, uint32_t icd_idx,
-                                            LUID luid, uint32_t *icd_phys_devs_array_count,
+VkResult enumerate_adapter_physical_devices(struct loader_instance *inst, struct loader_icd_term *icd_term, LUID luid,
+                                            uint32_t *icd_phys_devs_array_count,
                                             struct loader_icd_physical_devices *icd_phys_devs_array) {
     uint32_t count = 0;
     VkResult res = icd_term->scanned_icd->EnumerateAdapterPhysicalDevices(icd_term->instance, luid, &count, NULL);
@@ -856,7 +856,6 @@ VkResult enumerate_adapter_physical_devices(struct loader_instance *inst, struct
     }
     if (!already_enumerated) {
         next_icd_phys_devs->device_count = count;
-        next_icd_phys_devs->icd_index = icd_idx;
         next_icd_phys_devs->icd_term = icd_term;
         next_icd_phys_devs->windows_adapter_luid = luid;
         (*icd_phys_devs_array_count)++;
@@ -982,18 +981,20 @@ VkResult windows_read_sorted_physical_devices(struct loader_instance *inst, uint
         (*icd_phys_devs_array)[*icd_phys_devs_array_count].physical_devices = NULL;
 
         icd_term = inst->icd_terms;
-        for (uint32_t icd_idx = 0; NULL != icd_term; icd_term = icd_term->next, icd_idx++) {
+        while (NULL != icd_term) {
             // This is the new behavior, which cannot be run unless the ICD provides EnumerateAdapterPhysicalDevices
             if (icd_term->scanned_icd->EnumerateAdapterPhysicalDevices == NULL) {
+                icd_term = icd_term->next;
                 continue;
             }
 
-            res = enumerate_adapter_physical_devices(inst, icd_term, icd_idx, description.AdapterLuid, icd_phys_devs_array_count,
+            res = enumerate_adapter_physical_devices(inst, icd_term, description.AdapterLuid, icd_phys_devs_array_count,
                                                      *icd_phys_devs_array);
             if (res == VK_ERROR_OUT_OF_HOST_MEMORY) {
                 adapter->lpVtbl->Release(adapter);
                 goto out;
             }
+            icd_term = icd_term->next;
         }
 
         adapter->lpVtbl->Release(adapter);
index ba35c3f1ff09450c223f4338c8ed3268ca3cb10a..14766b88ec4c4916141432a80ea69037ca58d635 100644 (file)
@@ -138,8 +138,7 @@ LOADER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDev
     // sufficient
     if (!strcmp(name, "GetDeviceQueue2")) {
         struct loader_device *dev = NULL;
-        uint32_t index = 0;
-        struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, &index);
+        struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev);
         if (NULL != icd_term && dev != NULL) {
             const struct loader_instance *inst = icd_term->this_instance;
             uint32_t api_version =
@@ -769,6 +768,10 @@ out:
 
             free_loader_settings(ptr_instance, &ptr_instance->settings);
 
+            loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)&ptr_instance->surfaces_list);
+            loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)&ptr_instance->debug_utils_messengers_list);
+            loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)&ptr_instance->debug_report_callbacks_list);
+
             loader_instance_heap_free(ptr_instance, ptr_instance->disp);
             // Remove any created VK_EXT_debug_report or VK_EXT_debug_utils items
             destroy_debug_callbacks_chain(ptr_instance, pAllocator);
@@ -842,6 +845,10 @@ LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance,
 
     free_loader_settings(ptr_instance, &ptr_instance->settings);
 
+    loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)&ptr_instance->surfaces_list);
+    loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)&ptr_instance->debug_utils_messengers_list);
+    loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)&ptr_instance->debug_report_callbacks_list);
+
     loader_destroy_pointer_layer_list(ptr_instance, &ptr_instance->expanded_activated_layer_list);
     loader_destroy_pointer_layer_list(ptr_instance, &ptr_instance->app_activated_layer_list);
 
index ad4d6b90538b06cb49071d132d1a4596e54c79e0..5183f11f1fd2665de67b725839ed3efbdd37f7c3 100644 (file)
@@ -180,8 +180,6 @@ LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroySurfaceKHR(VkInstance instance
     loader_inst->disp->layer_inst_disp.DestroySurfaceKHR(loader_inst->instance, surface, pAllocator);
 }
 
-// TODO probably need to lock around all the loader_get_instance() calls.
-
 // This is the instance chain terminator function for DestroySurfaceKHR
 VKAPI_ATTR void VKAPI_CALL terminator_DestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface,
                                                         const VkAllocationCallbacks *pAllocator) {
@@ -189,25 +187,21 @@ VKAPI_ATTR void VKAPI_CALL terminator_DestroySurfaceKHR(VkInstance instance, VkS
 
     VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)(surface);
     if (NULL != icd_surface) {
-        if (NULL != icd_surface->real_icd_surfaces) {
-            uint32_t i = 0;
-            for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
-                if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
-                    if (NULL != icd_term->dispatch.DestroySurfaceKHR &&
-                        (VkSurfaceKHR)(uintptr_t)NULL != icd_surface->real_icd_surfaces[i]) {
-                        icd_term->dispatch.DestroySurfaceKHR(icd_term->instance, icd_surface->real_icd_surfaces[i], pAllocator);
-                        icd_surface->real_icd_surfaces[i] = (VkSurfaceKHR)(uintptr_t)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((VkSurfaceKHR)(uintptr_t)NULL == icd_surface->real_icd_surfaces[i]);
+        for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
+            if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
+                if (NULL != icd_term->dispatch.DestroySurfaceKHR && icd_term->surface_list.list[icd_surface->surface_index]) {
+                    icd_term->dispatch.DestroySurfaceKHR(icd_term->instance,
+                                                         icd_term->surface_list.list[icd_surface->surface_index], pAllocator);
+                    icd_term->surface_list.list[icd_surface->surface_index] = (VkSurfaceKHR)(uintptr_t)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((VkSurfaceKHR)(uintptr_t)NULL == icd_term->surface_list.list[icd_surface->surface_index]);
             }
-            loader_instance_heap_free(loader_inst, icd_surface->real_icd_surfaces);
         }
-
+        loader_release_object_from_list(&loader_inst->surfaces_list, icd_surface->surface_index);
         loader_instance_heap_free(loader_inst, (void *)(uintptr_t)surface);
     }
 }
@@ -259,10 +253,11 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceSupportKHR(VkP
     }
 
     VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)surface;
-    if (NULL != icd_surface->real_icd_surfaces &&
-        (VkSurfaceKHR)(uintptr_t)NULL != icd_surface->real_icd_surfaces[phys_dev_term->icd_index]) {
+    if (NULL != icd_term->surface_list.list &&
+        icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
+        icd_term->surface_list.list[icd_surface->surface_index]) {
         return icd_term->dispatch.GetPhysicalDeviceSurfaceSupportKHR(
-            phys_dev_term->phys_dev, queueFamilyIndex, icd_surface->real_icd_surfaces[phys_dev_term->icd_index], pSupported);
+            phys_dev_term->phys_dev, queueFamilyIndex, icd_term->surface_list.list[icd_surface->surface_index], pSupported);
     }
 
     return icd_term->dispatch.GetPhysicalDeviceSurfaceSupportKHR(phys_dev_term->phys_dev, queueFamilyIndex, surface, pSupported);
@@ -313,10 +308,12 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceCapabilitiesKH
     }
 
     VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)surface;
-    if (NULL != icd_surface->real_icd_surfaces &&
-        (VkSurfaceKHR)(uintptr_t)NULL != icd_surface->real_icd_surfaces[phys_dev_term->icd_index]) {
+    if (NULL != phys_dev_term->this_icd_term->surface_list.list &&
+        phys_dev_term->this_icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
+        phys_dev_term->this_icd_term->surface_list.list[icd_surface->surface_index]) {
         return icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilitiesKHR(
-            phys_dev_term->phys_dev, icd_surface->real_icd_surfaces[phys_dev_term->icd_index], pSurfaceCapabilities);
+            phys_dev_term->phys_dev, phys_dev_term->this_icd_term->surface_list.list[icd_surface->surface_index],
+            pSurfaceCapabilities);
     }
 
     return icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilitiesKHR(phys_dev_term->phys_dev, surface, pSurfaceCapabilities);
@@ -369,11 +366,12 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceFormatsKHR(VkP
     }
 
     VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)surface;
-    if (NULL != icd_surface->real_icd_surfaces &&
-        (VkSurfaceKHR)(uintptr_t)NULL != icd_surface->real_icd_surfaces[phys_dev_term->icd_index]) {
-        return icd_term->dispatch.GetPhysicalDeviceSurfaceFormatsKHR(phys_dev_term->phys_dev,
-                                                                     icd_surface->real_icd_surfaces[phys_dev_term->icd_index],
-                                                                     pSurfaceFormatCount, pSurfaceFormats);
+    if (NULL != phys_dev_term->this_icd_term->surface_list.list &&
+        phys_dev_term->this_icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
+        phys_dev_term->this_icd_term->surface_list.list[icd_surface->surface_index]) {
+        return icd_term->dispatch.GetPhysicalDeviceSurfaceFormatsKHR(
+            phys_dev_term->phys_dev, phys_dev_term->this_icd_term->surface_list.list[icd_surface->surface_index],
+            pSurfaceFormatCount, pSurfaceFormats);
     }
 
     return icd_term->dispatch.GetPhysicalDeviceSurfaceFormatsKHR(phys_dev_term->phys_dev, surface, pSurfaceFormatCount,
@@ -427,10 +425,12 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfacePresentModesKH
     }
 
     VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)surface;
-    if (NULL != icd_surface->real_icd_surfaces &&
-        (VkSurfaceKHR)(uintptr_t)NULL != icd_surface->real_icd_surfaces[phys_dev_term->icd_index]) {
+    if (NULL != phys_dev_term->this_icd_term->surface_list.list &&
+        phys_dev_term->this_icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
+        phys_dev_term->this_icd_term->surface_list.list[icd_surface->surface_index]) {
         return icd_term->dispatch.GetPhysicalDeviceSurfacePresentModesKHR(
-            phys_dev_term->phys_dev, icd_surface->real_icd_surfaces[phys_dev_term->icd_index], pPresentModeCount, pPresentModes);
+            phys_dev_term->phys_dev, phys_dev_term->this_icd_term->surface_list.list[icd_surface->surface_index], pPresentModeCount,
+            pPresentModes);
     }
 
     return icd_term->dispatch.GetPhysicalDeviceSurfacePresentModesKHR(phys_dev_term->phys_dev, surface, pPresentModeCount,
@@ -462,9 +462,8 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateSwapchainKHR(VkDevice devic
 
 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo,
                                                              const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchain) {
-    uint32_t icd_index = 0;
     struct loader_device *dev;
-    struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, &icd_index);
+    struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev);
     if (NULL == icd_term || NULL == dev) {
         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
                    "vkCreateSwapchainKHR Terminator: device handle. This is likely the result of a "
@@ -485,20 +484,19 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateSwapchainKHR(VkDevice device, co
         return VK_SUCCESS;
     }
     VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pCreateInfo->surface;
-    if (NULL != icd_surface->real_icd_surfaces) {
-        if ((VkSurfaceKHR)(uintptr_t)NULL != 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(VkSwapchainCreateInfoKHR));
-            pCreateCopy->surface = icd_surface->real_icd_surfaces[icd_index];
-            return dev->loader_dispatch.extension_terminator_dispatch.CreateSwapchainKHR(device, pCreateCopy, pAllocator,
-                                                                                         pSwapchain);
+    if (NULL != icd_term->surface_list.list &&
+        icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
+        icd_term->surface_list.list[icd_surface->surface_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(VkSwapchainCreateInfoKHR));
+        pCreateCopy->surface = icd_term->surface_list.list[icd_surface->surface_index];
+        return dev->loader_dispatch.extension_terminator_dispatch.CreateSwapchainKHR(device, pCreateCopy, pAllocator, pSwapchain);
     }
     return dev->loader_dispatch.extension_terminator_dispatch.CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain);
 }
@@ -550,25 +548,72 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkQueuePresentKHR(VkQueue queue, co
     return disp->QueuePresentKHR(queue, pPresentInfo);
 }
 
-VkIcdSurface *AllocateIcdSurfaceStruct(struct loader_instance *instance, size_t base_size, size_t platform_size) {
+VkResult allocate_icd_surface_struct(struct loader_instance *instance, size_t base_size, size_t platform_size,
+                                     VkIcdSurface **out_icd_surface) {
+    uint32_t next_index = 0;
+    VkIcdSurface *icd_surface = NULL;
+    VkResult res = loader_get_next_available_entry(instance, &instance->surfaces_list, &next_index);
+    if (res != VK_SUCCESS) {
+        goto out;
+    }
+
     // Next, if so, proceed with the implementation of this function:
-    VkIcdSurface *pIcdSurface = loader_instance_heap_alloc(instance, sizeof(VkIcdSurface), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
-    if (pIcdSurface != NULL) {
-        // Setup the new sizes and offsets so we can grow the structures in the
-        // future without having problems
-        pIcdSurface->base_size = (uint32_t)base_size;
-        pIcdSurface->platform_size = (uint32_t)platform_size;
-        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_calloc(instance, sizeof(VkSurfaceKHR) * instance->icd_terms_count,
-                                                                     VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
-        if (pIcdSurface->real_icd_surfaces == NULL) {
-            loader_instance_heap_free(instance, pIcdSurface);
-            pIcdSurface = NULL;
+    icd_surface = loader_instance_heap_alloc(instance, sizeof(VkIcdSurface), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+    if (icd_surface == NULL) {
+        res = VK_ERROR_OUT_OF_HOST_MEMORY;
+        goto out;
+    }
+    // Setup the new sizes and offsets so we can grow the structures in the
+    // future without having problems
+    icd_surface->base_size = (uint32_t)base_size;
+    icd_surface->platform_size = (uint32_t)platform_size;
+    icd_surface->non_platform_offset = (uint32_t)((uint8_t *)(&icd_surface->base_size) - (uint8_t *)icd_surface);
+    icd_surface->entire_size = sizeof(VkIcdSurface);
+    icd_surface->surface_index = next_index;
+
+    for (struct loader_icd_term *icd_term = instance->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
+        if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
+            if (icd_term->surface_list.list == NULL) {
+                res =
+                    loader_init_generic_list(instance, (struct loader_generic_list *)&icd_term->surface_list, sizeof(VkSurfaceKHR));
+                if (res != VK_SUCCESS) {
+                    goto out;
+                }
+            } else if (icd_term->surface_list.capacity <= next_index * sizeof(VkSurfaceKHR)) {
+                res = loader_resize_generic_list(instance, (struct loader_generic_list *)&icd_term->surface_list);
+                if (res != VK_SUCCESS) {
+                    goto out;
+                }
+            }
+        }
+    }
+
+    *out_icd_surface = icd_surface;
+out:
+    if (res != VK_SUCCESS) {
+        loader_instance_heap_free(instance, icd_surface);
+        // cleanup of icd_term->surface_list is done during instance destruction
+    }
+    return res;
+}
+
+void cleanup_surface_creation(struct loader_instance *loader_inst, VkResult result, VkIcdSurface *icd_surface,
+                              const VkAllocationCallbacks *pAllocator) {
+    if (VK_SUCCESS != result && NULL != icd_surface) {
+        for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
+            if (NULL != icd_term->surface_list.list &&
+                icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
+                icd_term->surface_list.list[icd_surface->surface_index] && NULL != icd_term->dispatch.DestroySurfaceKHR) {
+                icd_term->dispatch.DestroySurfaceKHR(icd_term->instance, icd_term->surface_list.list[icd_surface->surface_index],
+                                                     pAllocator);
+            }
+        }
+        if (loader_inst->surfaces_list.list &&
+            loader_inst->surfaces_list.capacity > icd_surface->surface_index * sizeof(VkBool32)) {
+            loader_inst->surfaces_list.list[icd_surface->surface_index] = VK_FALSE;
         }
+        loader_instance_heap_free(loader_inst, icd_surface);
     }
-    return pIcdSurface;
 }
 
 #if defined(VK_USE_PLATFORM_WIN32_KHR)
@@ -592,9 +637,9 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateWin32SurfaceKHR(VkInstance
 // This is the instance chain terminator function for CreateWin32SurfaceKHR
 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateWin32SurfaceKHR(VkInstance instance, const VkWin32SurfaceCreateInfoKHR *pCreateInfo,
                                                                 const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
-    VkResult vkRes = VK_SUCCESS;
-    VkIcdSurface *pIcdSurface = NULL;
-    uint32_t i = 0;
+    VkResult result = VK_SUCCESS;
+    VkIcdSurface *icd_surface = NULL;
+    loader_platform_thread_lock_mutex(&loader_lock);
 
     // Initialize pSurface to NULL just to be safe.
     *pSurface = VK_NULL_HANDLE;
@@ -603,53 +648,40 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateWin32SurfaceKHR(VkInstance insta
     if (!loader_inst->wsi_win32_surface_enabled) {
         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
                    "VK_KHR_win32_surface extension not enabled. vkCreateWin32SurfaceKHR not executed!");
-        vkRes = VK_ERROR_EXTENSION_NOT_PRESENT;
+        result = VK_ERROR_EXTENSION_NOT_PRESENT;
         goto out;
     }
 
     // Next, if so, proceed with the implementation of this function:
-    pIcdSurface = AllocateIcdSurfaceStruct(loader_inst, sizeof(pIcdSurface->win_surf.base), sizeof(pIcdSurface->win_surf));
-    if (pIcdSurface == NULL) {
-        vkRes = VK_ERROR_OUT_OF_HOST_MEMORY;
+    result =
+        allocate_icd_surface_struct(loader_inst, sizeof(icd_surface->win_surf.base), sizeof(icd_surface->win_surf), &icd_surface);
+    if (VK_SUCCESS != result) {
         goto out;
     }
 
-    pIcdSurface->win_surf.base.platform = VK_ICD_WSI_PLATFORM_WIN32;
-    pIcdSurface->win_surf.hinstance = pCreateInfo->hinstance;
-    pIcdSurface->win_surf.hwnd = pCreateInfo->hwnd;
+    icd_surface->win_surf.base.platform = VK_ICD_WSI_PLATFORM_WIN32;
+    icd_surface->win_surf.hinstance = pCreateInfo->hinstance;
+    icd_surface->win_surf.hwnd = pCreateInfo->hwnd;
 
     // Loop through each ICD and determine if they need to create a surface
-    for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
+    for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
         if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
             if (NULL != icd_term->dispatch.CreateWin32SurfaceKHR) {
-                vkRes = icd_term->dispatch.CreateWin32SurfaceKHR(icd_term->instance, pCreateInfo, pAllocator,
-                                                                 &pIcdSurface->real_icd_surfaces[i]);
-                if (VK_SUCCESS != vkRes) {
+                result = icd_term->dispatch.CreateWin32SurfaceKHR(icd_term->instance, pCreateInfo, pAllocator,
+                                                                  &icd_term->surface_list.list[icd_surface->surface_index]);
+                if (VK_SUCCESS != result) {
                     goto out;
                 }
             }
         }
     }
 
-    *pSurface = (VkSurfaceKHR)(uintptr_t)pIcdSurface;
+    *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface;
 
 out:
-
-    if (VK_SUCCESS != vkRes && NULL != pIcdSurface) {
-        if (NULL != pIcdSurface->real_icd_surfaces) {
-            i = 0;
-            for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
-                if ((VkSurfaceKHR)(uintptr_t)NULL != pIcdSurface->real_icd_surfaces[i] &&
-                    NULL != icd_term->dispatch.DestroySurfaceKHR) {
-                    icd_term->dispatch.DestroySurfaceKHR(icd_term->instance, pIcdSurface->real_icd_surfaces[i], pAllocator);
-                }
-            }
-            loader_instance_heap_free(loader_inst, pIcdSurface->real_icd_surfaces);
-        }
-        loader_instance_heap_free(loader_inst, pIcdSurface);
-    }
-
-    return vkRes;
+    cleanup_surface_creation(loader_inst, result, icd_surface, pAllocator);
+    loader_platform_thread_unlock_mutex(&loader_lock);
+    return result;
 }
 
 // This is the trampoline entrypoint for
@@ -713,62 +745,50 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateWaylandSurfaceKHR(VkInstanc
 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateWaylandSurfaceKHR(VkInstance instance,
                                                                   const VkWaylandSurfaceCreateInfoKHR *pCreateInfo,
                                                                   const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
-    VkResult vkRes = VK_SUCCESS;
-    VkIcdSurface *pIcdSurface = NULL;
-    uint32_t i = 0;
+    VkResult result = VK_SUCCESS;
+    VkIcdSurface *icd_surface = NULL;
+    loader_platform_thread_lock_mutex(&loader_lock);
 
     // First, check to ensure the appropriate extension was enabled:
     struct loader_instance *loader_inst = loader_get_instance(instance);
     if (!loader_inst->wsi_wayland_surface_enabled) {
         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
                    "VK_KHR_wayland_surface extension not enabled. vkCreateWaylandSurfaceKHR not executed!");
-        vkRes = VK_ERROR_EXTENSION_NOT_PRESENT;
+        result = VK_ERROR_EXTENSION_NOT_PRESENT;
         goto out;
     }
 
     // Next, if so, proceed with the implementation of this function:
-    pIcdSurface = AllocateIcdSurfaceStruct(loader_inst, sizeof(pIcdSurface->wayland_surf.base), sizeof(pIcdSurface->wayland_surf));
-    if (pIcdSurface == NULL) {
-        vkRes = VK_ERROR_OUT_OF_HOST_MEMORY;
+    result = allocate_icd_surface_struct(loader_inst, sizeof(icd_surface->wayland_surf.base), sizeof(icd_surface->wayland_surf),
+                                         &icd_surface);
+    if (VK_SUCCESS != result) {
         goto out;
     }
 
-    pIcdSurface->wayland_surf.base.platform = VK_ICD_WSI_PLATFORM_WAYLAND;
-    pIcdSurface->wayland_surf.display = pCreateInfo->display;
-    pIcdSurface->wayland_surf.surface = pCreateInfo->surface;
+    icd_surface->wayland_surf.base.platform = VK_ICD_WSI_PLATFORM_WAYLAND;
+    icd_surface->wayland_surf.display = pCreateInfo->display;
+    icd_surface->wayland_surf.surface = pCreateInfo->surface;
 
     // Loop through each ICD and determine if they need to create a surface
-    for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
+    for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
         if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
             if (NULL != icd_term->dispatch.CreateWaylandSurfaceKHR) {
-                vkRes = icd_term->dispatch.CreateWaylandSurfaceKHR(icd_term->instance, pCreateInfo, pAllocator,
-                                                                   &pIcdSurface->real_icd_surfaces[i]);
-                if (VK_SUCCESS != vkRes) {
+                result = icd_term->dispatch.CreateWaylandSurfaceKHR(icd_term->instance, pCreateInfo, pAllocator,
+                                                                    &icd_term->surface_list.list[icd_surface->surface_index]);
+                if (VK_SUCCESS != result) {
                     goto out;
                 }
             }
         }
     }
 
-    *pSurface = (VkSurfaceKHR)(uintptr_t)pIcdSurface;
+    *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface;
 
 out:
+    cleanup_surface_creation(loader_inst, result, icd_surface, pAllocator);
+    loader_platform_thread_unlock_mutex(&loader_lock);
 
-    if (VK_SUCCESS != vkRes && NULL != pIcdSurface) {
-        if (NULL != pIcdSurface->real_icd_surfaces) {
-            i = 0;
-            for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
-                if ((VkSurfaceKHR)(uintptr_t)NULL != pIcdSurface->real_icd_surfaces[i] &&
-                    NULL != icd_term->dispatch.DestroySurfaceKHR) {
-                    icd_term->dispatch.DestroySurfaceKHR(icd_term->instance, pIcdSurface->real_icd_surfaces[i], pAllocator);
-                }
-            }
-            loader_instance_heap_free(loader_inst, pIcdSurface->real_icd_surfaces);
-        }
-        loader_instance_heap_free(loader_inst, pIcdSurface);
-    }
-
-    return vkRes;
+    return result;
 }
 
 // This is the trampoline entrypoint for
@@ -835,62 +855,50 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateXcbSurfaceKHR(VkInstance in
 // This is the instance chain terminator function for CreateXcbSurfaceKHR
 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateXcbSurfaceKHR(VkInstance instance, const VkXcbSurfaceCreateInfoKHR *pCreateInfo,
                                                               const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
-    VkResult vkRes = VK_SUCCESS;
-    VkIcdSurface *pIcdSurface = NULL;
-    uint32_t i = 0;
+    VkResult result = VK_SUCCESS;
+    VkIcdSurface *icd_surface = NULL;
+    loader_platform_thread_lock_mutex(&loader_lock);
 
     // First, check to ensure the appropriate extension was enabled:
     struct loader_instance *loader_inst = loader_get_instance(instance);
     if (!loader_inst->wsi_xcb_surface_enabled) {
         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
                    "VK_KHR_xcb_surface extension not enabled. vkCreateXcbSurfaceKHR not executed!");
-        vkRes = VK_ERROR_EXTENSION_NOT_PRESENT;
+        result = VK_ERROR_EXTENSION_NOT_PRESENT;
         goto out;
     }
 
     // Next, if so, proceed with the implementation of this function:
-    pIcdSurface = AllocateIcdSurfaceStruct(loader_inst, sizeof(pIcdSurface->xcb_surf.base), sizeof(pIcdSurface->xcb_surf));
-    if (pIcdSurface == NULL) {
-        vkRes = VK_ERROR_OUT_OF_HOST_MEMORY;
+    result =
+        allocate_icd_surface_struct(loader_inst, sizeof(icd_surface->xcb_surf.base), sizeof(icd_surface->xcb_surf), &icd_surface);
+    if (VK_SUCCESS != result) {
         goto out;
     }
 
-    pIcdSurface->xcb_surf.base.platform = VK_ICD_WSI_PLATFORM_XCB;
-    pIcdSurface->xcb_surf.connection = pCreateInfo->connection;
-    pIcdSurface->xcb_surf.window = pCreateInfo->window;
+    icd_surface->xcb_surf.base.platform = VK_ICD_WSI_PLATFORM_XCB;
+    icd_surface->xcb_surf.connection = pCreateInfo->connection;
+    icd_surface->xcb_surf.window = pCreateInfo->window;
 
     // Loop through each ICD and determine if they need to create a surface
-    for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
+    for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
         if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
             if (NULL != icd_term->dispatch.CreateXcbSurfaceKHR) {
-                vkRes = icd_term->dispatch.CreateXcbSurfaceKHR(icd_term->instance, pCreateInfo, pAllocator,
-                                                               &pIcdSurface->real_icd_surfaces[i]);
-                if (VK_SUCCESS != vkRes) {
+                result = icd_term->dispatch.CreateXcbSurfaceKHR(icd_term->instance, pCreateInfo, pAllocator,
+                                                                &icd_term->surface_list.list[icd_surface->surface_index]);
+                if (VK_SUCCESS != result) {
                     goto out;
                 }
             }
         }
     }
 
-    *pSurface = (VkSurfaceKHR)(uintptr_t)pIcdSurface;
+    *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface;
 
 out:
+    cleanup_surface_creation(loader_inst, result, icd_surface, pAllocator);
+    loader_platform_thread_unlock_mutex(&loader_lock);
 
-    if (VK_SUCCESS != vkRes && NULL != pIcdSurface) {
-        if (NULL != pIcdSurface->real_icd_surfaces) {
-            i = 0;
-            for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
-                if ((VkSurfaceKHR)(uintptr_t)NULL != pIcdSurface->real_icd_surfaces[i] &&
-                    NULL != icd_term->dispatch.DestroySurfaceKHR) {
-                    icd_term->dispatch.DestroySurfaceKHR(icd_term->instance, pIcdSurface->real_icd_surfaces[i], pAllocator);
-                }
-            }
-            loader_instance_heap_free(loader_inst, pIcdSurface->real_icd_surfaces);
-        }
-        loader_instance_heap_free(loader_inst, pIcdSurface);
-    }
-
-    return vkRes;
+    return result;
 }
 
 // This is the trampoline entrypoint for
@@ -960,62 +968,50 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateXlibSurfaceKHR(VkInstance i
 // This is the instance chain terminator function for CreateXlibSurfaceKHR
 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateXlibSurfaceKHR(VkInstance instance, const VkXlibSurfaceCreateInfoKHR *pCreateInfo,
                                                                const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
-    VkResult vkRes = VK_SUCCESS;
-    VkIcdSurface *pIcdSurface = NULL;
-    uint32_t i = 0;
+    VkResult result = VK_SUCCESS;
+    VkIcdSurface *icd_surface = NULL;
+    loader_platform_thread_lock_mutex(&loader_lock);
 
     // First, check to ensure the appropriate extension was enabled:
     struct loader_instance *loader_inst = loader_get_instance(instance);
     if (!loader_inst->wsi_xlib_surface_enabled) {
         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
                    "VK_KHR_xlib_surface extension not enabled. vkCreateXlibSurfaceKHR not executed!");
-        vkRes = VK_ERROR_EXTENSION_NOT_PRESENT;
+        result = VK_ERROR_EXTENSION_NOT_PRESENT;
         goto out;
     }
 
     // Next, if so, proceed with the implementation of this function:
-    pIcdSurface = AllocateIcdSurfaceStruct(loader_inst, sizeof(pIcdSurface->xlib_surf.base), sizeof(pIcdSurface->xlib_surf));
-    if (pIcdSurface == NULL) {
-        vkRes = VK_ERROR_OUT_OF_HOST_MEMORY;
+    result =
+        allocate_icd_surface_struct(loader_inst, sizeof(icd_surface->xlib_surf.base), sizeof(icd_surface->xlib_surf), &icd_surface);
+    if (VK_SUCCESS != result) {
         goto out;
     }
 
-    pIcdSurface->xlib_surf.base.platform = VK_ICD_WSI_PLATFORM_XLIB;
-    pIcdSurface->xlib_surf.dpy = pCreateInfo->dpy;
-    pIcdSurface->xlib_surf.window = pCreateInfo->window;
+    icd_surface->xlib_surf.base.platform = VK_ICD_WSI_PLATFORM_XLIB;
+    icd_surface->xlib_surf.dpy = pCreateInfo->dpy;
+    icd_surface->xlib_surf.window = pCreateInfo->window;
 
     // Loop through each ICD and determine if they need to create a surface
-    for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
+    for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
         if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
             if (NULL != icd_term->dispatch.CreateXlibSurfaceKHR) {
-                vkRes = icd_term->dispatch.CreateXlibSurfaceKHR(icd_term->instance, pCreateInfo, pAllocator,
-                                                                &pIcdSurface->real_icd_surfaces[i]);
-                if (VK_SUCCESS != vkRes) {
+                result = icd_term->dispatch.CreateXlibSurfaceKHR(icd_term->instance, pCreateInfo, pAllocator,
+                                                                 &icd_term->surface_list.list[icd_surface->surface_index]);
+                if (VK_SUCCESS != result) {
                     goto out;
                 }
             }
         }
     }
 
-    *pSurface = (VkSurfaceKHR)(uintptr_t)pIcdSurface;
+    *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface;
 
 out:
+    cleanup_surface_creation(loader_inst, result, icd_surface, pAllocator);
+    loader_platform_thread_unlock_mutex(&loader_lock);
 
-    if (VK_SUCCESS != vkRes && NULL != pIcdSurface) {
-        if (NULL != pIcdSurface->real_icd_surfaces) {
-            i = 0;
-            for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
-                if ((VkSurfaceKHR)(uintptr_t)NULL != pIcdSurface->real_icd_surfaces[i] &&
-                    NULL != icd_term->dispatch.DestroySurfaceKHR) {
-                    icd_term->dispatch.DestroySurfaceKHR(icd_term->instance, pIcdSurface->real_icd_surfaces[i], pAllocator);
-                }
-            }
-            loader_instance_heap_free(loader_inst, pIcdSurface->real_icd_surfaces);
-        }
-        loader_instance_heap_free(loader_inst, pIcdSurface);
-    }
-
-    return vkRes;
+    return result;
 }
 
 // This is the trampoline entrypoint for
@@ -1084,63 +1080,50 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDirectFBSurfaceEXT(VkInstance in
                                                                    const VkDirectFBSurfaceCreateInfoEXT *pCreateInfo,
                                                                    const VkAllocationCallbacks *pAllocator,
                                                                    VkSurfaceKHR *pSurface) {
-    VkResult vkRes = VK_SUCCESS;
-    VkIcdSurface *pIcdSurface = NULL;
-    uint32_t i = 0;
+    VkResult result = VK_SUCCESS;
+    VkIcdSurface *icd_surface = NULL;
+    loader_platform_thread_lock_mutex(&loader_lock);
 
     // First, check to ensure the appropriate extension was enabled:
     struct loader_instance *loader_inst = loader_get_instance(instance);
     if (!loader_inst->wsi_directfb_surface_enabled) {
         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
                    "VK_EXT_directfb_surface extension not enabled. vkCreateDirectFBSurfaceEXT not executed!");
-        vkRes = VK_ERROR_EXTENSION_NOT_PRESENT;
+        result = VK_ERROR_EXTENSION_NOT_PRESENT;
         goto out;
     }
 
     // Next, if so, proceed with the implementation of this function:
-    pIcdSurface =
-        AllocateIcdSurfaceStruct(loader_inst, sizeof(pIcdSurface->directfb_surf.base), sizeof(pIcdSurface->directfb_surf));
-    if (pIcdSurface == NULL) {
-        vkRes = VK_ERROR_OUT_OF_HOST_MEMORY;
+    result = allocate_icd_surface_struct(loader_inst, sizeof(icd_surface->directfb_surf.base), sizeof(icd_surface->directfb_surf),
+                                         &icd_surface);
+    if (VK_SUCCESS != result) {
         goto out;
     }
 
-    pIcdSurface->directfb_surf.base.platform = VK_ICD_WSI_PLATFORM_DIRECTFB;
-    pIcdSurface->directfb_surf.dfb = pCreateInfo->dfb;
-    pIcdSurface->directfb_surf.surface = pCreateInfo->surface;
+    icd_surface->directfb_surf.base.platform = VK_ICD_WSI_PLATFORM_DIRECTFB;
+    icd_surface->directfb_surf.dfb = pCreateInfo->dfb;
+    icd_surface->directfb_surf.surface = pCreateInfo->surface;
 
     // Loop through each ICD and determine if they need to create a surface
-    for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
+    for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
         if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
             if (NULL != icd_term->dispatch.CreateDirectFBSurfaceEXT) {
-                vkRes = icd_term->dispatch.CreateDirectFBSurfaceEXT(icd_term->instance, pCreateInfo, pAllocator,
-                                                                    &pIcdSurface->real_icd_surfaces[i]);
-                if (VK_SUCCESS != vkRes) {
+                result = icd_term->dispatch.CreateDirectFBSurfaceEXT(icd_term->instance, pCreateInfo, pAllocator,
+                                                                     &icd_term->surface_list.list[icd_surface->surface_index]);
+                if (VK_SUCCESS != result) {
                     goto out;
                 }
             }
         }
     }
 
-    *pSurface = (VkSurfaceKHR)(uintptr_t)pIcdSurface;
+    *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface;
 
 out:
+    cleanup_surface_creation(loader_inst, result, icd_surface, pAllocator);
+    loader_platform_thread_unlock_mutex(&loader_lock);
 
-    if (VK_SUCCESS != vkRes && NULL != pIcdSurface) {
-        if (NULL != pIcdSurface->real_icd_surfaces) {
-            i = 0;
-            for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
-                if ((VkSurfaceKHR)(uintptr_t)NULL != pIcdSurface->real_icd_surfaces[i] &&
-                    NULL != icd_term->dispatch.DestroySurfaceKHR) {
-                    icd_term->dispatch.DestroySurfaceKHR(icd_term->instance, pIcdSurface->real_icd_surfaces[i], pAllocator);
-                }
-            }
-            loader_instance_heap_free(loader_inst, pIcdSurface->real_icd_surfaces);
-        }
-        loader_instance_heap_free(loader_inst, pIcdSurface);
-    }
-
-    return vkRes;
+    return result;
 }
 
 // This is the trampoline entrypoint for
@@ -1219,16 +1202,16 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateAndroidSurfaceKHR(VkInstance ins
     }
 
     // Next, if so, proceed with the implementation of this function:
-    VkIcdSurfaceAndroid *pIcdSurface =
+    VkIcdSurfaceAndroid *icd_surface =
         loader_instance_heap_alloc(loader_inst, sizeof(VkIcdSurfaceAndroid), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
-    if (pIcdSurface == NULL) {
+    if (icd_surface == NULL) {
         return VK_ERROR_OUT_OF_HOST_MEMORY;
     }
 
-    pIcdSurface->base.platform = VK_ICD_WSI_PLATFORM_ANDROID;
-    pIcdSurface->window = pCreateInfo->window;
+    icd_surface->base.platform = VK_ICD_WSI_PLATFORM_ANDROID;
+    icd_surface->window = pCreateInfo->window;
 
-    *pSurface = (VkSurfaceKHR)(uintptr_t)pIcdSurface;
+    *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface;
 
     return VK_SUCCESS;
 }
@@ -1254,58 +1237,47 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateHeadlessSurfaceEXT(VkInstance in
                                                                    const VkHeadlessSurfaceCreateInfoEXT *pCreateInfo,
                                                                    const VkAllocationCallbacks *pAllocator,
                                                                    VkSurfaceKHR *pSurface) {
-    struct loader_instance *inst = loader_get_instance(instance);
-    VkIcdSurface *pIcdSurface = NULL;
-    VkResult vkRes = VK_SUCCESS;
-    uint32_t i = 0;
+    VkResult result = VK_SUCCESS;
+    VkIcdSurface *icd_surface = NULL;
+    loader_platform_thread_lock_mutex(&loader_lock);
 
-    if (!inst->wsi_headless_surface_enabled) {
-        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
+    // First, check to ensure the appropriate extension was enabled:
+    struct loader_instance *loader_inst = loader_get_instance(instance);
+    if (!loader_inst->wsi_headless_surface_enabled) {
+        loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
                    "VK_EXT_headless_surface extension not enabled.  "
                    "vkCreateHeadlessSurfaceEXT not executed!");
         return VK_SUCCESS;
     }
 
     // Next, if so, proceed with the implementation of this function:
-    pIcdSurface = AllocateIcdSurfaceStruct(inst, sizeof(pIcdSurface->headless_surf.base), sizeof(pIcdSurface->headless_surf));
-    if (pIcdSurface == NULL) {
-        vkRes = VK_ERROR_OUT_OF_HOST_MEMORY;
+    result = allocate_icd_surface_struct(loader_inst, sizeof(icd_surface->headless_surf.base), sizeof(icd_surface->headless_surf),
+                                         &icd_surface);
+    if (VK_SUCCESS != result) {
         goto out;
     }
 
-    pIcdSurface->headless_surf.base.platform = VK_ICD_WSI_PLATFORM_HEADLESS;
+    icd_surface->headless_surf.base.platform = VK_ICD_WSI_PLATFORM_HEADLESS;
     // Loop through each ICD and determine if they need to create a surface
-    for (struct loader_icd_term *icd_term = inst->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
+    for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
         if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
             if (NULL != icd_term->dispatch.CreateHeadlessSurfaceEXT) {
-                vkRes = icd_term->dispatch.CreateHeadlessSurfaceEXT(icd_term->instance, pCreateInfo, pAllocator,
-                                                                    &pIcdSurface->real_icd_surfaces[i]);
-                if (VK_SUCCESS != vkRes) {
+                result = icd_term->dispatch.CreateHeadlessSurfaceEXT(icd_term->instance, pCreateInfo, pAllocator,
+                                                                     &icd_term->surface_list.list[icd_surface->surface_index]);
+                if (VK_SUCCESS != result) {
                     goto out;
                 }
             }
         }
     }
 
-    *pSurface = (VkSurfaceKHR)(uintptr_t)pIcdSurface;
+    *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface;
 
 out:
+    cleanup_surface_creation(loader_inst, result, icd_surface, pAllocator);
+    loader_platform_thread_unlock_mutex(&loader_lock);
 
-    if (VK_SUCCESS != vkRes && NULL != pIcdSurface) {
-        if (NULL != pIcdSurface->real_icd_surfaces) {
-            i = 0;
-            for (struct loader_icd_term *icd_term = inst->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
-                if ((VkSurfaceKHR)(uintptr_t)NULL != pIcdSurface->real_icd_surfaces[i] &&
-                    NULL != icd_term->dispatch.DestroySurfaceKHR) {
-                    icd_term->dispatch.DestroySurfaceKHR(icd_term->instance, pIcdSurface->real_icd_surfaces[i], pAllocator);
-                }
-            }
-            loader_instance_heap_free(inst, pIcdSurface->real_icd_surfaces);
-        }
-        loader_instance_heap_free(inst, pIcdSurface);
-    }
-
-    return vkRes;
+    return result;
 }
 
 // Ensure we are properly setting VK_USE_PLATFORM_METAL_EXT, VK_USE_PLATFORM_IOS_MVK, and VK_USE_PLATFORM_MACOS_MVK.
@@ -1356,61 +1328,49 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateMacOSSurfaceMVK(VkInstance
 // This is the instance chain terminator function for CreateMacOSSurfaceKHR
 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateMacOSSurfaceMVK(VkInstance instance, const VkMacOSSurfaceCreateInfoMVK *pCreateInfo,
                                                                 const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
-    VkResult vkRes = VK_SUCCESS;
-    VkIcdSurface *pIcdSurface = NULL;
-    uint32_t i = 0;
+    VkResult result = VK_SUCCESS;
+    VkIcdSurface *icd_surface = NULL;
+    loader_platform_thread_lock_mutex(&loader_lock);
 
     // First, check to ensure the appropriate extension was enabled:
     struct loader_instance *loader_inst = loader_get_instance(instance);
     if (!loader_inst->wsi_macos_surface_enabled) {
         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
                    "VK_MVK_macos_surface extension not enabled. vkCreateMacOSSurfaceMVK not executed!");
-        vkRes = VK_ERROR_EXTENSION_NOT_PRESENT;
+        result = VK_ERROR_EXTENSION_NOT_PRESENT;
         goto out;
     }
 
     // Next, if so, proceed with the implementation of this function:
-    pIcdSurface = AllocateIcdSurfaceStruct(loader_inst, sizeof(pIcdSurface->macos_surf.base), sizeof(pIcdSurface->macos_surf));
-    if (pIcdSurface == NULL) {
-        vkRes = VK_ERROR_OUT_OF_HOST_MEMORY;
+    result = allocate_icd_surface_struct(loader_inst, sizeof(icd_surface->macos_surf.base), sizeof(icd_surface->macos_surf),
+                                         &icd_surface);
+    if (VK_SUCCESS != result) {
         goto out;
     }
 
-    pIcdSurface->macos_surf.base.platform = VK_ICD_WSI_PLATFORM_MACOS;
-    pIcdSurface->macos_surf.pView = pCreateInfo->pView;
+    icd_surface->macos_surf.base.platform = VK_ICD_WSI_PLATFORM_MACOS;
+    icd_surface->macos_surf.pView = pCreateInfo->pView;
 
     // Loop through each ICD and determine if they need to create a surface
-    for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
+    for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
         if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
             if (NULL != icd_term->dispatch.CreateMacOSSurfaceMVK) {
-                vkRes = icd_term->dispatch.CreateMacOSSurfaceMVK(icd_term->instance, pCreateInfo, pAllocator,
-                                                                 &pIcdSurface->real_icd_surfaces[i]);
-                if (VK_SUCCESS != vkRes) {
+                result = icd_term->dispatch.CreateMacOSSurfaceMVK(icd_term->instance, pCreateInfo, pAllocator,
+                                                                  &icd_term->surface_list.list[icd_surface->surface_index]);
+                if (VK_SUCCESS != result) {
                     goto out;
                 }
             }
         }
     }
 
-    *pSurface = (VkSurfaceKHR)(uintptr_t)pIcdSurface;
+    *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface;
 
 out:
+    cleanup_surface_creation(loader_inst, result, icd_surface, pAllocator);
+    loader_platform_thread_unlock_mutex(&loader_lock);
 
-    if (VK_SUCCESS != vkRes && NULL != pIcdSurface) {
-        if (NULL != pIcdSurface->real_icd_surfaces) {
-            i = 0;
-            for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
-                if ((VkSurfaceKHR)(uintptr_t)NULL != pIcdSurface->real_icd_surfaces[i] &&
-                    NULL != icd_term->dispatch.DestroySurfaceKHR) {
-                    icd_term->dispatch.DestroySurfaceKHR(icd_term->instance, pIcdSurface->real_icd_surfaces[i], pAllocator);
-                }
-            }
-            loader_instance_heap_free(loader_inst, pIcdSurface->real_icd_surfaces);
-        }
-        loader_instance_heap_free(loader_inst, pIcdSurface);
-    }
-
-    return vkRes;
+    return result;
 }
 
 #endif  // VK_USE_PLATFORM_MACOS_MVK
@@ -1447,16 +1407,16 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateIOSSurfaceMVK(VkInstance instanc
     }
 
     // Next, if so, proceed with the implementation of this function:
-    VkIcdSurfaceIOS *pIcdSurface =
+    VkIcdSurfaceIOS *icd_surface =
         loader_instance_heap_alloc(loader_inst, sizeof(VkIcdSurfaceIOS), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
-    if (pIcdSurface == NULL) {
+    if (icd_surface == NULL) {
         return VK_ERROR_OUT_OF_HOST_MEMORY;
     }
 
-    pIcdSurface->base.platform = VK_ICD_WSI_PLATFORM_IOS;
-    pIcdSurface->pView = pCreateInfo->pView;
+    icd_surface->base.platform = VK_ICD_WSI_PLATFORM_IOS;
+    icd_surface->pView = pCreateInfo->pView;
 
-    *pSurface = (VkSurfaceKHR)(uintptr_t)pIcdSurface;
+    *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface;
 
     return VK_SUCCESS;
 }
@@ -1486,60 +1446,49 @@ vkCreateStreamDescriptorSurfaceGGP(VkInstance instance, const VkStreamDescriptor
 VKAPI_ATTR VkResult VKAPI_CALL
 terminator_CreateStreamDescriptorSurfaceGGP(VkInstance instance, const VkStreamDescriptorSurfaceCreateInfoGGP *pCreateInfo,
                                             const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
-    VkResult vkRes = VK_SUCCESS;
-    VkIcdSurface *pIcdSurface = NULL;
-    uint32_t i = 0;
+    VkResult result = VK_SUCCESS;
+    VkIcdSurface *icd_surface = NULL;
+    loader_platform_thread_lock_mutex(&loader_lock);
 
     // First, check to ensure the appropriate extension was enabled:
     struct loader_instance *loader_inst = loader_get_instance(instance);
     if (!loader_inst->wsi_ggp_surface_enabled) {
         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
                    "VK_GGP_stream_descriptor_surface extension not enabled. vkCreateStreamDescriptorSurfaceGGP not executed!");
-        vkRes = VK_ERROR_EXTENSION_NOT_PRESENT;
+        result = VK_ERROR_EXTENSION_NOT_PRESENT;
         goto out;
     }
 
     // Next, if so, proceed with the implementation of this function:
-    pIcdSurface = AllocateIcdSurfaceStruct(loader_inst, sizeof(pIcdSurface->ggp_surf.base), sizeof(pIcdSurface->ggp_surf));
-    if (pIcdSurface == NULL) {
-        vkRes = VK_ERROR_OUT_OF_HOST_MEMORY;
+    result =
+        allocate_icd_surface_struct(loader_inst, sizeof(icd_surface->ggp_surf.base), sizeof(icd_surface->ggp_surf), &icd_surface);
+    if (VK_SUCCESS != result) {
         goto out;
     }
 
-    pIcdSurface->ggp_surf.base.platform = VK_ICD_WSI_PLATFORM_GGP;
-    pIcdSurface->ggp_surf.streamDescriptor = pCreateInfo->streamDescriptor;
+    icd_surface->ggp_surf.base.platform = VK_ICD_WSI_PLATFORM_GGP;
+    icd_surface->ggp_surf.streamDescriptor = pCreateInfo->streamDescriptor;
 
     // Loop through each ICD and determine if they need to create a surface
-    for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
+    for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
         if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
             if (NULL != icd_term->dispatch.CreateStreamDescriptorSurfaceGGP) {
-                vkRes = icd_term->dispatch.CreateStreamDescriptorSurfaceGGP(icd_term->instance, pCreateInfo, pAllocator,
-                                                                            &pIcdSurface->real_icd_surfaces[i]);
-                if (VK_SUCCESS != vkRes) {
+                result = icd_term->dispatch.CreateStreamDescriptorSurfaceGGP(
+                    icd_term->instance, pCreateInfo, pAllocator, &icd_term->surface_list.list[icd_surface->surface_index]);
+                if (VK_SUCCESS != result) {
                     goto out;
                 }
             }
         }
     }
 
-    *pSurface = (VkSurfaceKHR)(uintptr_t)pIcdSurface;
+    *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface;
 
 out:
+    cleanup_surface_creation(loader_inst, result, icd_surface, pAllocator);
+    loader_platform_thread_unlock_mutex(&loader_lock);
 
-    if (VK_SUCCESS != vkRes && NULL != pIcdSurface) {
-        if (NULL != pIcdSurface->real_icd_surfaces) {
-            i = 0;
-            for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
-                if ((VkSurfaceKHR)(uintptr_t)NULL != pIcdSurface->real_icd_surfaces[i] &&
-                    NULL != icd_term->dispatch.DestroySurfaceKHR) {
-                    icd_term->dispatch.DestroySurfaceKHR(icd_term->instance, pIcdSurface->real_icd_surfaces[i], pAllocator);
-                }
-            }
-            loader_instance_heap_free(loader_inst, pIcdSurface->real_icd_surfaces);
-        }
-        loader_instance_heap_free(loader_inst, pIcdSurface);
-    }
-    return vkRes;
+    return result;
 }
 
 #endif  // VK_USE_PLATFORM_GGP
@@ -1563,7 +1512,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateMetalSurfaceEXT(VkInstance insta
                                                                 const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
     VkResult result = VK_SUCCESS;
     VkIcdSurface *icd_surface = NULL;
-    uint32_t i;
+    loader_platform_thread_lock_mutex(&loader_lock);
 
     // First, check to ensure the appropriate extension was enabled:
     struct loader_instance *loader_inst = loader_get_instance(instance);
@@ -1573,9 +1522,9 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateMetalSurfaceEXT(VkInstance insta
     }
 
     // Next, if so, proceed with the implementation of this function:
-    icd_surface = AllocateIcdSurfaceStruct(loader_inst, sizeof(icd_surface->metal_surf.base), sizeof(icd_surface->metal_surf));
-    if (icd_surface == NULL) {
-        result = VK_ERROR_OUT_OF_HOST_MEMORY;
+    result = allocate_icd_surface_struct(loader_inst, sizeof(icd_surface->metal_surf.base), sizeof(icd_surface->metal_surf),
+                                         &icd_surface);
+    if (VK_SUCCESS != result) {
         goto out;
     }
 
@@ -1583,13 +1532,12 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateMetalSurfaceEXT(VkInstance insta
     icd_surface->metal_surf.pLayer = pCreateInfo->pLayer;
 
     // Loop through each ICD and determine if they need to create a surface
-    i = 0;
-    for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next, ++i) {
+    for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
         if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
-            if (icd_term->dispatch.CreateMetalSurfaceEXT != NULL) {
+            if (NULL != icd_term->dispatch.CreateMetalSurfaceEXT) {
                 result = icd_term->dispatch.CreateMetalSurfaceEXT(icd_term->instance, pCreateInfo, pAllocator,
-                                                                  &icd_surface->real_icd_surfaces[i]);
-                if (result != VK_SUCCESS) {
+                                                                  &icd_term->surface_list.list[icd_surface->surface_index]);
+                if (VK_SUCCESS != result) {
                     goto out;
                 }
             }
@@ -1598,18 +1546,9 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateMetalSurfaceEXT(VkInstance insta
     *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface;
 
 out:
-    if (result != VK_SUCCESS && icd_surface != NULL) {
-        if (icd_surface->real_icd_surfaces != NULL) {
-            i = 0;
-            for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next, ++i) {
-                if (icd_surface->real_icd_surfaces[i] == VK_NULL_HANDLE && icd_term->dispatch.DestroySurfaceKHR != NULL) {
-                    icd_term->dispatch.DestroySurfaceKHR(icd_term->instance, icd_surface->real_icd_surfaces[i], pAllocator);
-                }
-            }
-            loader_instance_heap_free(loader_inst, icd_surface->real_icd_surfaces);
-        }
-        loader_instance_heap_free(loader_inst, icd_surface);
-    }
+    cleanup_surface_creation(loader_inst, result, icd_surface, pAllocator);
+    loader_platform_thread_unlock_mutex(&loader_lock);
+
     return result;
 }
 
@@ -1635,62 +1574,50 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateScreenSurfaceQNX(VkInstance
 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateScreenSurfaceQNX(VkInstance instance,
                                                                  const VkScreenSurfaceCreateInfoQNX *pCreateInfo,
                                                                  const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
-    VkResult vkRes = VK_SUCCESS;
-    VkIcdSurface *pIcdSurface = NULL;
-    uint32_t i = 0;
+    VkResult result = VK_SUCCESS;
+    VkIcdSurface *icd_surface = NULL;
+    loader_platform_thread_lock_mutex(&loader_lock);
 
     // First, check to ensure the appropriate extension was enabled:
     struct loader_instance *loader_inst = loader_get_instance(instance);
     if (!loader_inst->wsi_screen_surface_enabled) {
         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
                    "VK_QNX_screen_surface extension not enabled. vkCreateScreenSurfaceQNX not executed!");
-        vkRes = VK_ERROR_EXTENSION_NOT_PRESENT;
+        result = VK_ERROR_EXTENSION_NOT_PRESENT;
         goto out;
     }
 
     // Next, if so, proceed with the implementation of this function:
-    pIcdSurface = AllocateIcdSurfaceStruct(loader_inst, sizeof(pIcdSurface->screen_surf.base), sizeof(pIcdSurface->screen_surf));
-    if (pIcdSurface == NULL) {
-        vkRes = VK_ERROR_OUT_OF_HOST_MEMORY;
+    result = allocate_icd_surface_struct(loader_inst, sizeof(icd_surface->screen_surf.base), sizeof(icd_surface->screen_surf),
+                                         &icd_surface);
+    if (VK_SUCCESS != result) {
         goto out;
     }
 
-    pIcdSurface->screen_surf.base.platform = VK_ICD_WSI_PLATFORM_SCREEN;
-    pIcdSurface->screen_surf.context = pCreateInfo->context;
-    pIcdSurface->screen_surf.window = pCreateInfo->window;
+    icd_surface->screen_surf.base.platform = VK_ICD_WSI_PLATFORM_SCREEN;
+    icd_surface->screen_surf.context = pCreateInfo->context;
+    icd_surface->screen_surf.window = pCreateInfo->window;
 
     // Loop through each ICD and determine if they need to create a surface
-    for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
+    for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
         if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
             if (NULL != icd_term->dispatch.CreateScreenSurfaceQNX) {
-                vkRes = icd_term->dispatch.CreateScreenSurfaceQNX(icd_term->instance, pCreateInfo, pAllocator,
-                                                                  &pIcdSurface->real_icd_surfaces[i]);
-                if (VK_SUCCESS != vkRes) {
+                result = icd_term->dispatch.CreateScreenSurfaceQNX(icd_term->instance, pCreateInfo, pAllocator,
+                                                                   &icd_term->surface_list.list[icd_surface->surface_index]);
+                if (VK_SUCCESS != result) {
                     goto out;
                 }
             }
         }
     }
 
-    *pSurface = (VkSurfaceKHR)(uintptr_t)pIcdSurface;
+    *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface;
 
 out:
+    cleanup_surface_creation(loader_inst, result, icd_surface, pAllocator);
+    loader_platform_thread_unlock_mutex(&loader_lock);
 
-    if (VK_SUCCESS != vkRes && NULL != pIcdSurface) {
-        if (NULL != pIcdSurface->real_icd_surfaces) {
-            i = 0;
-            for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
-                if ((VkSurfaceKHR)(uintptr_t)NULL != pIcdSurface->real_icd_surfaces[i] &&
-                    NULL != icd_term->dispatch.DestroySurfaceKHR) {
-                    icd_term->dispatch.DestroySurfaceKHR(icd_term->instance, pIcdSurface->real_icd_surfaces[i], pAllocator);
-                }
-            }
-            loader_instance_heap_free(loader_inst, pIcdSurface->real_icd_surfaces);
-        }
-        loader_instance_heap_free(loader_inst, pIcdSurface);
-    }
-
-    return vkRes;
+    return result;
 }
 
 // This is the trampoline entrypoint for
@@ -1755,61 +1682,49 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateViSurfaceNN(VkInstance inst
 // This is the instance chain terminator function for CreateViSurfaceNN
 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateViSurfaceNN(VkInstance instance, const VkViSurfaceCreateInfoNN *pCreateInfo,
                                                             const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
-    VkResult vkRes = VK_SUCCESS;
-    VkIcdSurface *pIcdSurface = NULL;
-    uint32_t i = 0;
+    VkResult result = VK_SUCCESS;
+    VkIcdSurface *icd_surface = NULL;
+    loader_platform_thread_lock_mutex(&loader_lock);
 
     // First, check to ensure the appropriate extension was enabled:
     struct loader_instance *loader_inst = loader_get_instance(instance);
     if (!loader_inst->wsi_vi_surface_enabled) {
         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
                    "VK_NN_vi_surface extension not enabled. vkCreateViSurfaceNN not executed!");
-        vkRes = VK_ERROR_EXTENSION_NOT_PRESENT;
+        result = VK_ERROR_EXTENSION_NOT_PRESENT;
         goto out;
     }
 
     // Next, if so, proceed with the implementation of this function:
-    pIcdSurface = AllocateIcdSurfaceStruct(loader_inst, sizeof(pIcdSurface->vi_surf.base), sizeof(pIcdSurface->vi_surf));
-    if (pIcdSurface == NULL) {
-        vkRes = VK_ERROR_OUT_OF_HOST_MEMORY;
+    result =
+        allocate_icd_surface_struct(loader_inst, sizeof(icd_surface->vi_surf.base), sizeof(icd_surface->vi_surf), &icd_surface);
+    if (VK_SUCCESS != result) {
         goto out;
     }
 
-    pIcdSurface->vi_surf.base.platform = VK_ICD_WSI_PLATFORM_VI;
-    pIcdSurface->vi_surf.window = pCreateInfo->window;
+    icd_surface->vi_surf.base.platform = VK_ICD_WSI_PLATFORM_VI;
+    icd_surface->vi_surf.window = pCreateInfo->window;
 
     // Loop through each ICD and determine if they need to create a surface
-    for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
+    for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
         if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
             if (NULL != icd_term->dispatch.CreateViSurfaceNN) {
-                vkRes = icd_term->dispatch.CreateViSurfaceNN(icd_term->instance, pCreateInfo, pAllocator,
-                                                             &pIcdSurface->real_icd_surfaces[i]);
-                if (VK_SUCCESS != vkRes) {
+                result = icd_term->dispatch.CreateViSurfaceNN(icd_term->instance, pCreateInfo, pAllocator,
+                                                              &icd_term->surface_list.list[icd_surface->surface_index]);
+                if (VK_SUCCESS != result) {
                     goto out;
                 }
             }
         }
     }
 
-    *pSurface = (VkSurfaceKHR)(uintptr_t)pIcdSurface;
+    *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface;
 
 out:
+    cleanup_surface_creation(loader_inst, result, icd_surface, pAllocator);
+    loader_platform_thread_unlock_mutex(&loader_lock);
 
-    if (VK_SUCCESS != vkRes && NULL != pIcdSurface) {
-        if (NULL != pIcdSurface->real_icd_surfaces) {
-            i = 0;
-            for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
-                if ((VkSurfaceKHR)(uintptr_t)NULL != pIcdSurface->real_icd_surfaces[i] &&
-                    NULL != icd_term->dispatch.DestroySurfaceKHR) {
-                    icd_term->dispatch.DestroySurfaceKHR(icd_term->instance, pIcdSurface->real_icd_surfaces[i], pAllocator);
-                }
-            }
-            loader_instance_heap_free(loader_inst, pIcdSurface->real_icd_surfaces);
-        }
-        loader_instance_heap_free(loader_inst, pIcdSurface);
-    }
-
-    return vkRes;
+    return result;
 }
 
 #endif  // VK_USE_PLATFORM_VI_NN
@@ -2081,66 +1996,55 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDisplayPlaneSurfaceKHR(VkInstanc
                                                                        const VkDisplaySurfaceCreateInfoKHR *pCreateInfo,
                                                                        const VkAllocationCallbacks *pAllocator,
                                                                        VkSurfaceKHR *pSurface) {
-    struct loader_instance *inst = loader_get_instance(instance);
-    VkIcdSurface *pIcdSurface = NULL;
-    VkResult vkRes = VK_SUCCESS;
-    uint32_t i = 0;
+    VkResult result = VK_SUCCESS;
+    VkIcdSurface *icd_surface = NULL;
+    loader_platform_thread_lock_mutex(&loader_lock);
 
-    if (!inst->wsi_display_enabled) {
-        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
+    // First, check to ensure the appropriate extension was enabled:
+    struct loader_instance *loader_inst = loader_get_instance(instance);
+    if (!loader_inst->wsi_display_enabled) {
+        loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
                    "VK_KHR_surface extension not enabled. vkCreateDisplayPlaneSurfaceKHR not executed!");
-        vkRes = VK_ERROR_EXTENSION_NOT_PRESENT;
+        result = VK_ERROR_EXTENSION_NOT_PRESENT;
         goto out;
     }
 
     // Next, if so, proceed with the implementation of this function:
-    pIcdSurface = AllocateIcdSurfaceStruct(inst, sizeof(pIcdSurface->display_surf.base), sizeof(pIcdSurface->display_surf));
-    if (pIcdSurface == NULL) {
-        vkRes = VK_ERROR_OUT_OF_HOST_MEMORY;
+    result = allocate_icd_surface_struct(loader_inst, sizeof(icd_surface->display_surf.base), sizeof(icd_surface->display_surf),
+                                         &icd_surface);
+    if (VK_SUCCESS != result) {
         goto out;
     }
 
-    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;
+    icd_surface->display_surf.base.platform = VK_ICD_WSI_PLATFORM_DISPLAY;
+    icd_surface->display_surf.displayMode = pCreateInfo->displayMode;
+    icd_surface->display_surf.planeIndex = pCreateInfo->planeIndex;
+    icd_surface->display_surf.planeStackIndex = pCreateInfo->planeStackIndex;
+    icd_surface->display_surf.transform = pCreateInfo->transform;
+    icd_surface->display_surf.globalAlpha = pCreateInfo->globalAlpha;
+    icd_surface->display_surf.alphaMode = pCreateInfo->alphaMode;
+    icd_surface->display_surf.imageExtent = pCreateInfo->imageExtent;
 
     // Loop through each ICD and determine if they need to create a surface
-    for (struct loader_icd_term *icd_term = inst->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
+    for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
         if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
             if (NULL != icd_term->dispatch.CreateDisplayPlaneSurfaceKHR) {
-                vkRes = icd_term->dispatch.CreateDisplayPlaneSurfaceKHR(icd_term->instance, pCreateInfo, pAllocator,
-                                                                        &pIcdSurface->real_icd_surfaces[i]);
-                if (VK_SUCCESS != vkRes) {
+                result = icd_term->dispatch.CreateDisplayPlaneSurfaceKHR(icd_term->instance, pCreateInfo, pAllocator,
+                                                                         &icd_term->surface_list.list[icd_surface->surface_index]);
+                if (VK_SUCCESS != result) {
                     goto out;
                 }
             }
         }
     }
 
-    *pSurface = (VkSurfaceKHR)(uintptr_t)pIcdSurface;
+    *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface;
 
 out:
+    cleanup_surface_creation(loader_inst, result, icd_surface, pAllocator);
+    loader_platform_thread_unlock_mutex(&loader_lock);
 
-    if (VK_SUCCESS != vkRes && NULL != pIcdSurface) {
-        if (NULL != pIcdSurface->real_icd_surfaces) {
-            i = 0;
-            for (struct loader_icd_term *icd_term = inst->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
-                if ((VkSurfaceKHR)(uintptr_t)NULL != pIcdSurface->real_icd_surfaces[i] &&
-                    NULL != icd_term->dispatch.DestroySurfaceKHR) {
-                    icd_term->dispatch.DestroySurfaceKHR(icd_term->instance, pIcdSurface->real_icd_surfaces[i], pAllocator);
-                }
-            }
-            loader_instance_heap_free(inst, pIcdSurface->real_icd_surfaces);
-        }
-        loader_instance_heap_free(inst, pIcdSurface);
-    }
-
-    return vkRes;
+    return result;
 }
 
 // EXT_display_swapchain Extension command
@@ -2162,9 +2066,8 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateSharedSwapchainsKHR(VkDevice dev
                                                                     const VkSwapchainCreateInfoKHR *pCreateInfos,
                                                                     const VkAllocationCallbacks *pAllocator,
                                                                     VkSwapchainKHR *pSwapchains) {
-    uint32_t icd_index = 0;
     struct loader_device *dev;
-    struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, &icd_index);
+    struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev);
     if (NULL == icd_term || NULL == dev) {
         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
                    "vkCreateSharedSwapchainsKHR Terminator: Invalid device handle. This is likely the result of a "
@@ -2179,7 +2082,9 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateSharedSwapchainsKHR(VkDevice dev
         return VK_SUCCESS;
     }
     VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pCreateInfos->surface;
-    if ((VkSurfaceKHR)(uintptr_t)NULL != icd_surface->real_icd_surfaces[icd_index]) {
+    if (NULL != icd_term->surface_list.list &&
+        icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
+        icd_term->surface_list.list[icd_surface->surface_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.
@@ -2189,7 +2094,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateSharedSwapchainsKHR(VkDevice dev
         }
         memcpy(pCreateCopy, pCreateInfos, sizeof(VkSwapchainCreateInfoKHR) * swapchainCount);
         for (uint32_t sc = 0; sc < swapchainCount; sc++) {
-            pCreateCopy[sc].surface = icd_surface->real_icd_surfaces[icd_index];
+            pCreateCopy[sc].surface = icd_term->surface_list.list[icd_surface->surface_index];
         }
         return dev->loader_dispatch.extension_terminator_dispatch.CreateSharedSwapchainsKHR(device, swapchainCount, pCreateCopy,
                                                                                             pAllocator, pSwapchains);
@@ -2224,9 +2129,8 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupSurfacePresentModes
 
 VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDeviceGroupSurfacePresentModesKHR(VkDevice device, VkSurfaceKHR surface,
                                                                                VkDeviceGroupPresentModeFlagsKHR *pModes) {
-    uint32_t icd_index = 0;
     struct loader_device *dev;
-    struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, &icd_index);
+    struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev);
     if (NULL == icd_term || NULL == dev) {
         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
                    "vkGetDeviceGroupSurfacePresentModesKHR: Invalid device "
@@ -2241,9 +2145,11 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDeviceGroupSurfacePresentModesKHR(V
         return VK_SUCCESS;
     }
     VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)surface;
-    if (NULL != icd_surface->real_icd_surfaces && (VkSurfaceKHR)(uintptr_t)NULL != icd_surface->real_icd_surfaces[icd_index]) {
+    if (NULL != icd_term->surface_list.list &&
+        icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
+        icd_term->surface_list.list[icd_surface->surface_index]) {
         return dev->loader_dispatch.extension_terminator_dispatch.GetDeviceGroupSurfacePresentModesKHR(
-            device, icd_surface->real_icd_surfaces[icd_index], pModes);
+            device, icd_term->surface_list.list[icd_surface->surface_index], pModes);
     }
     return dev->loader_dispatch.extension_terminator_dispatch.GetDeviceGroupSurfacePresentModesKHR(device, surface, pModes);
 }
@@ -2278,10 +2184,11 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDevicePresentRectanglesKHR(
         return VK_SUCCESS;
     }
     VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)(surface);
-    uint8_t icd_index = phys_dev_term->icd_index;
-    if (NULL != icd_surface->real_icd_surfaces && NULL != (void *)(uintptr_t)(icd_surface->real_icd_surfaces[icd_index])) {
+    if (NULL != icd_term->surface_list.list &&
+        icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
+        icd_term->surface_list.list[icd_surface->surface_index]) {
         return icd_term->dispatch.GetPhysicalDevicePresentRectanglesKHR(
-            phys_dev_term->phys_dev, icd_surface->real_icd_surfaces[icd_index], pRectCount, pRects);
+            phys_dev_term->phys_dev, icd_term->surface_list.list[icd_surface->surface_index], pRectCount, pRects);
     }
     return icd_term->dispatch.GetPhysicalDevicePresentRectanglesKHR(phys_dev_term->phys_dev, surface, pRectCount, pRects);
 }
@@ -2532,9 +2439,8 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateImagePipeSurfaceFUCHSIA(VkInstan
                                                                         const VkImagePipeSurfaceCreateInfoFUCHSIA *pCreateInfo,
                                                                         const VkAllocationCallbacks *pAllocator,
                                                                         VkSurfaceKHR *pSurface) {
-    VkResult vkRes = VK_SUCCESS;
-    VkIcdSurface *pIcdSurface = NULL;
-    uint32_t i = 0;
+    VkResult result = VK_SUCCESS;
+    VkIcdSurface *icd_surface = NULL;
 
     // Initialize pSurface to NULL just to be safe.
     *pSurface = VK_NULL_HANDLE;
@@ -2544,52 +2450,38 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateImagePipeSurfaceFUCHSIA(VkInstan
         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
                    "VK_FUCHSIA_imagepipe_surface extension not enabled.  "
                    "vkCreateImagePipeSurfaceFUCHSIA not executed!");
-        vkRes = VK_ERROR_EXTENSION_NOT_PRESENT;
+        result = VK_ERROR_EXTENSION_NOT_PRESENT;
         goto out;
     }
 
     // Next, if so, proceed with the implementation of this function:
-    pIcdSurface =
-        AllocateIcdSurfaceStruct(loader_inst, sizeof(pIcdSurface->imagepipe_surf.base), sizeof(pIcdSurface->imagepipe_surf));
-    if (pIcdSurface == NULL) {
-        vkRes = VK_ERROR_OUT_OF_HOST_MEMORY;
+    result = allocate_icd_surface_struct(loader_inst, sizeof(icd_surface->imagepipe_surf.base), sizeof(icd_surface->imagepipe_surf),
+                                         &icd_surface);
+    if (VK_SUCCESS != result) {
         goto out;
     }
 
-    pIcdSurface->imagepipe_surf.base.platform = VK_ICD_WSI_PLATFORM_FUCHSIA;
+    icd_surface->imagepipe_surf.base.platform = VK_ICD_WSI_PLATFORM_FUCHSIA;
 
     // Loop through each ICD and determine if they need to create a surface
-    for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
+    for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
         if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
             if (NULL != icd_term->dispatch.CreateImagePipeSurfaceFUCHSIA) {
-                vkRes = icd_term->dispatch.CreateImagePipeSurfaceFUCHSIA(icd_term->instance, pCreateInfo, pAllocator,
-                                                                         &pIcdSurface->real_icd_surfaces[i]);
-                if (VK_SUCCESS != vkRes) {
+                result = icd_term->dispatch.CreateImagePipeSurfaceFUCHSIA(icd_term->instance, pCreateInfo, pAllocator,
+                                                                          &icd_term->surface_list.list[icd_surface->surface_index]);
+                if (VK_SUCCESS != result) {
                     goto out;
                 }
             }
         }
     }
 
-    *pSurface = (VkSurfaceKHR)(uintptr_t)pIcdSurface;
+    *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface;
 
 out:
+    cleanup_surface_creation(loader_inst, result, icd_surface, pAllocator);
 
-    if (VK_SUCCESS != vkRes && NULL != pIcdSurface) {
-        if (NULL != pIcdSurface->real_icd_surfaces) {
-            i = 0;
-            for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
-                if ((VkSurfaceKHR)(uintptr_t)NULL != pIcdSurface->real_icd_surfaces[i] &&
-                    NULL != icd_term->dispatch.DestroySurfaceKHR) {
-                    icd_term->dispatch.DestroySurfaceKHR(icd_term->instance, pIcdSurface->real_icd_surfaces[i], pAllocator);
-                }
-            }
-            loader_instance_heap_free(loader_inst, pIcdSurface->real_icd_surfaces);
-        }
-        loader_instance_heap_free(loader_inst, pIcdSurface);
-    }
-
-    return vkRes;
+    return result;
 }
 #endif  // VK_USE_PLATFORM_FUCHSIA
 
@@ -2614,6 +2506,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceCapabilities2K
     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
     struct loader_instance *loader_inst = (struct loader_instance *)icd_term->this_instance;
+    VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pSurfaceInfo->surface;
 
     if (!loader_inst->wsi_surface_enabled) {
         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
@@ -2621,9 +2514,6 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceCapabilities2K
         return VK_SUCCESS;
     }
 
-    VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)(pSurfaceInfo->surface);
-    uint8_t icd_index = phys_dev_term->icd_index;
-
     if (icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilities2KHR != NULL) {
         VkBaseOutStructure *pNext = (VkBaseOutStructure *)pSurfaceCapabilities->pNext;
         while (pNext != NULL) {
@@ -2637,9 +2527,11 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceCapabilities2K
         }
 
         // Pass the call to the driver, possibly unwrapping the ICD surface
-        if (NULL != icd_surface->real_icd_surfaces && NULL != (void *)(uintptr_t)icd_surface->real_icd_surfaces[icd_index]) {
+        if (NULL != icd_term->surface_list.list &&
+            icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
+            icd_term->surface_list.list[icd_surface->surface_index]) {
             VkPhysicalDeviceSurfaceInfo2KHR info_copy = *pSurfaceInfo;
-            info_copy.surface = icd_surface->real_icd_surfaces[icd_index];
+            info_copy.surface = icd_term->surface_list.list[icd_surface->surface_index];
             return icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilities2KHR(phys_dev_term->phys_dev, &info_copy,
                                                                                pSurfaceCapabilities);
         } else {
@@ -2661,8 +2553,10 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceCapabilities2K
 
         // Write to the VkSurfaceCapabilities2KHR struct
         VkSurfaceKHR surface = pSurfaceInfo->surface;
-        if (NULL != icd_surface->real_icd_surfaces && NULL != (void *)(uintptr_t)(icd_surface->real_icd_surfaces[icd_index])) {
-            surface = icd_surface->real_icd_surfaces[icd_index];
+        if (NULL != icd_term->surface_list.list &&
+            icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
+            icd_term->surface_list.list[icd_surface->surface_index]) {
+            surface = icd_term->surface_list.list[icd_surface->surface_index];
         }
 
         // If the icd doesn't support VK_KHR_surface, then there are no capabilities
@@ -2714,13 +2608,14 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceFormats2KHR(Vk
     }
 
     VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)(pSurfaceInfo->surface);
-    uint8_t icd_index = phys_dev_term->icd_index;
 
     if (icd_term->dispatch.GetPhysicalDeviceSurfaceFormats2KHR != NULL) {
         // Pass the call to the driver, possibly unwrapping the ICD surface
-        if (NULL != icd_surface->real_icd_surfaces && NULL != (void *)(uintptr_t)(icd_surface->real_icd_surfaces[icd_index])) {
+        if (NULL != icd_term->surface_list.list &&
+            icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
+            icd_term->surface_list.list[icd_surface->surface_index]) {
             VkPhysicalDeviceSurfaceInfo2KHR info_copy = *pSurfaceInfo;
-            info_copy.surface = icd_surface->real_icd_surfaces[icd_index];
+            info_copy.surface = icd_term->surface_list.list[icd_surface->surface_index];
             return icd_term->dispatch.GetPhysicalDeviceSurfaceFormats2KHR(phys_dev_term->phys_dev, &info_copy, pSurfaceFormatCount,
                                                                           pSurfaceFormats);
         } else {
@@ -2740,8 +2635,10 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceFormats2KHR(Vk
         }
 
         VkSurfaceKHR surface = pSurfaceInfo->surface;
-        if (NULL != icd_surface->real_icd_surfaces && NULL != (void *)(uintptr_t)(icd_surface->real_icd_surfaces[icd_index])) {
-            surface = icd_surface->real_icd_surfaces[icd_index];
+        if (NULL != icd_term->surface_list.list &&
+            icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
+            icd_term->surface_list.list[icd_surface->surface_index]) {
+            surface = icd_term->surface_list.list[icd_surface->surface_index];
         }
 
         // If the icd doesn't support VK_KHR_surface, then there are no formats
index 07cc3f2d0d59aeee0b7ab0165d2bead3b1ebfe79..57675154ff7f2fa535e37324be1ed3b83737fa50 100644 (file)
@@ -66,7 +66,7 @@ typedef struct {
     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;
+    uint32_t surface_index;        // This surface's index into each drivers list of created surfaces
 } VkIcdSurface;
 
 bool wsi_swapchain_instance_gpa(struct loader_instance *ptr_instance, const char *name, void **addr);
index 62114f55a2765229b5c7e67f75db5a3ca9153f6a..58413042e122c0670a380f0299fcc9b2aba2a8f7 100644 (file)
@@ -542,7 +542,7 @@ class LoaderExtensionOutputGenerator(OutputGenerator):
         protos += 'VKAPI_ATTR VkResult VKAPI_CALL vkDevExtError(VkDevice dev) {\n'
         protos += '    struct loader_device *found_dev;\n'
         protos += '    // The device going in is a trampoline device\n'
-        protos += '    struct loader_icd_term *icd_term = loader_get_icd_and_device(dev, &found_dev, NULL);\n'
+        protos += '    struct loader_icd_term *icd_term = loader_get_icd_and_device(dev, &found_dev);\n'
         protos += '\n'
         protos += '    if (icd_term)\n'
         protos += '        loader_log(icd_term->this_instance, VULKAN_LOADER_ERROR_BIT, 0,\n'
@@ -1087,14 +1087,14 @@ class LoaderExtensionOutputGenerator(OutputGenerator):
                     requires_terminator = 1
                     always_use_param_name = False
                     surface_type_to_replace = 'VkSurfaceKHR'
-                    surface_name_replacement = 'icd_surface->real_icd_surfaces[icd_index]'
+                    surface_name_replacement = 'icd_term->surface_list[icd_surface->surface_index]'
                 if param.type == 'VkPhysicalDeviceSurfaceInfo2KHR':
                     has_surface = 1
                     surface_var_name = param.name + '->surface'
                     requires_terminator = 1
                     update_structure_surface = 1
                     update_structure_string = '        VkPhysicalDeviceSurfaceInfo2KHR info_copy = *pSurfaceInfo;\n'
-                    update_structure_string += '        info_copy.surface = icd_surface->real_icd_surfaces[icd_index];\n'
+                    update_structure_string += '        info_copy.surface = icd_term->surface_list[icd_surface->surface_index];\n'
                     always_use_param_name = False
                     surface_type_to_replace = 'VkPhysicalDeviceSurfaceInfo2KHR'
                     surface_name_replacement = '&info_copy'
@@ -1255,9 +1255,8 @@ class LoaderExtensionOutputGenerator(OutputGenerator):
                     funcs += '    }\n'
 
                     if has_surface == 1:
-                        funcs += '    VkIcdSurface *icd_surface = (VkIcdSurface *)(%s);\n' % (surface_var_name)
-                        funcs += '    uint8_t icd_index = phys_dev_term->icd_index;\n'
-                        funcs += '    if (NULL != icd_surface->real_icd_surfaces && NULL != (void *)icd_surface->real_icd_surfaces[icd_index]) {\n'
+                        funcs += '    VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)(%s);\n' % (surface_var_name)
+                        funcs += '    if (NULL != icd_term->surface_list.list && icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) && icd_term->surface_list[icd_surface->surface_index]) {\n'
 
                         # If there's a structure with a surface, we need to update its internals with the correct surface for the ICD
                         if update_structure_surface == 1:
@@ -1324,10 +1323,9 @@ class LoaderExtensionOutputGenerator(OutputGenerator):
                         phys_dev_check = 'VK_OBJECT_TYPE_PHYSICAL_DEVICE' if is_debug_utils else 'VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT'
                         surf_check = 'VK_OBJECT_TYPE_SURFACE_KHR' if is_debug_utils else 'VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT'
                         inst_check = 'VK_OBJECT_TYPE_INSTANCE' if is_debug_utils else 'VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT'
-                        funcs += '    uint32_t icd_index = 0;\n'
                         funcs += '    struct loader_device *dev;\n'
-                        funcs += f'    struct loader_icd_term *icd_term = loader_get_icd_and_device({ ext_cmd.params[0].name}, &dev, &icd_index);\n'
-                        funcs += f'    if (NULL == icd_term || NULL == dev) {{\n'
+                        funcs += f'    struct loader_icd_term *icd_term = loader_get_icd_and_device({ ext_cmd.params[0].name}, &dev);\n'
+                        funcs += '    if (NULL == icd_term || NULL == dev) {\n'
                         funcs += f'        loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0, "{ext_cmd.name[2:]}: Invalid device handle");\n'
                         funcs += '        abort(); /* Intentionally fail so user can correct issue. */\n'
                         funcs += '    }\n'
@@ -1341,8 +1339,9 @@ class LoaderExtensionOutputGenerator(OutputGenerator):
                         funcs += f'    }} else if ({debug_struct_name}->objectType == {surf_check}) {{\n'
                         funcs += '        if (NULL != dev && NULL != dev->loader_dispatch.core_dispatch.CreateSwapchainKHR) {\n'
                         funcs += f'            VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t){debug_struct_name}->{member_name};\n'
-                        funcs += '            if (NULL != icd_surface->real_icd_surfaces) {\n'
-                        funcs += f'                {local_struct}.{member_name} = (uint64_t)icd_surface->real_icd_surfaces[icd_index];\n'
+                        funcs += '            if (NULL != icd_term->surface_list.list && icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR)\n'
+                        funcs += '                && icd_term->surface_list.list[icd_surface->surface_index]) {\n'
+                        funcs += f'                {local_struct}.{member_name} = (uint64_t)icd_term->surface_list.list[icd_surface->surface_index];\n'
                         funcs += '            }\n'
                         funcs += '        }\n'
                         funcs += '    // If this is an instance we have to replace it with the proper one for the next call.\n'
@@ -1355,7 +1354,7 @@ class LoaderExtensionOutputGenerator(OutputGenerator):
                         dispatch = 'dev->loader_dispatch.'
                     else:
                         funcs += f'    struct loader_dev_dispatch_table *dispatch_table = loader_get_dev_dispatch({ext_cmd.params[0].name});\n'
-                        funcs += f'    if (NULL == dispatch_table) {{\n'
+                        funcs += '    if (NULL == dispatch_table) {\n'
                         funcs += f'        loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0, "{ext_cmd.ext_name}: Invalid device handle");\n'
                         funcs += '        abort(); /* Intentionally fail so user can correct issue. */\n'
                         funcs += '    }\n'
@@ -1374,7 +1373,7 @@ class LoaderExtensionOutputGenerator(OutputGenerator):
                         if param.type == 'VkPhysicalDevice':
                             funcs += 'phys_dev_term->phys_dev'
                         elif param.type == 'VkSurfaceKHR':
-                            funcs += 'icd_surface->real_icd_surfaces[icd_index]'
+                            funcs += 'icd_term->surface_list[icd_surface->surface_index]'
                         elif ('DebugMarkerSetObject' in ext_cmd.name or 'SetDebugUtilsObject' in ext_cmd.name) and param.name == 'pNameInfo':
                             funcs += '&local_name_info'
                         elif ('DebugMarkerSetObject' in ext_cmd.name or 'SetDebugUtilsObject' in ext_cmd.name) and param.name == 'pTagInfo':