Keep allocated debug callbacks until destroy instance
authorCharles Giessen <charles@lunarg.com>
Tue, 24 May 2022 23:30:23 +0000 (17:30 -0600)
committerCharles Giessen <46324611+charles-lunarg@users.noreply.github.com>
Fri, 27 May 2022 23:14:25 +0000 (17:14 -0600)
Previously the loader would destroy any debug callbacks created during instance creation
to later create new ones during instance destruction. This required a memory allocation
to occur inside vkDestroyInstance, which can cause leaks if an OOM occurs during
instance destruction.

This commit simplifies the logic by keeping around the allocations made during instance
creation by moving them into their own debug node chain. Then during instance destruction
moves them back.

Also renames several functions to better describe their intended purpose.

loader/debug_utils.c
loader/debug_utils.h
loader/gpa_helper.c
loader/loader.c
loader/loader_common.h
loader/trampoline.c
tests/loader_debug_ext_tests.cpp

index 564f3d3ef2c50d4da16efc728ff7e66dfb4a0586..fc3f9e01f1b0e87036014280d420d384114164c7 100644 (file)
@@ -37,6 +37,7 @@
 
 #include "allocation.h"
 #include "debug_utils.h"
+#include "log.h"
 #include "loader.h"
 #include "vk_loader_platform.h"
 
@@ -129,87 +130,23 @@ void util_DestroyDebugUtilsMessenger(struct loader_instance *inst, VkDebugUtilsM
     }
 }
 
-// This utility (used by vkInstanceCreateInfo(), looks at a pNext chain.  It
-// counts any VkDebugUtilsMessengerCreateInfoEXT structs that it finds.  It
-// then allocates array that can hold that many structs, as well as that many
-// VkDebugUtilsMessengerEXT handles.  It then copies each
-// VkDebugUtilsMessengerCreateInfoEXT, and initializes each handle.
-VkResult util_CopyDebugUtilsMessengerCreateInfos(const void *pChain, const VkAllocationCallbacks *pAllocator,
-                                                 uint32_t *num_messengers, VkDebugUtilsMessengerCreateInfoEXT **infos,
-                                                 VkDebugUtilsMessengerEXT **messengers) {
-    uint32_t n = *num_messengers = 0;
-    VkDebugUtilsMessengerCreateInfoEXT *pInfos = NULL;
-    VkDebugUtilsMessengerEXT *pMessengers = NULL;
-
+VkResult util_CreateDebugUtilsMessengers(struct loader_instance *inst, const void *pChain,
+                                         const VkAllocationCallbacks *pAllocator) {
     const void *pNext = pChain;
     while (pNext) {
-        // 1st, count the number VkDebugUtilsMessengerCreateInfoEXT:
-        if (((VkDebugUtilsMessengerCreateInfoEXT *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
-            n++;
-        }
-        pNext = (void *)((VkDebugUtilsMessengerCreateInfoEXT *)pNext)->pNext;
-    }
-    if (n == 0) {
-        return VK_SUCCESS;
-    }
-
-    // 2nd, allocate memory for each VkDebugUtilsMessengerCreateInfoEXT:
-    pInfos = *infos = ((VkDebugUtilsMessengerCreateInfoEXT *)loader_alloc(
-        pAllocator, n * sizeof(VkDebugUtilsMessengerCreateInfoEXT), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
-
-    if (!pInfos) {
-        return VK_ERROR_OUT_OF_HOST_MEMORY;
-    }
-    // 3rd, allocate memory for a unique handle for each callback:
-    pMessengers = *messengers = ((VkDebugUtilsMessengerEXT *)loader_alloc(pAllocator, n * sizeof(VkDebugUtilsMessengerEXT),
-                                                                          VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
-    if (NULL == pMessengers) {
-        loader_free(pAllocator, pInfos);
-        return VK_ERROR_OUT_OF_HOST_MEMORY;
-    }
-    // 4th, copy each VkDebugUtilsMessengerCreateInfoEXT for use by
-    // vkDestroyInstance, and assign a unique handle to each messenger (just
-    // use the address of the copied VkDebugUtilsMessengerCreateInfoEXT):
-    pNext = pChain;
-    while (pNext) {
-        if (((VkInstanceCreateInfo *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
-            memcpy(pInfos, pNext, sizeof(VkDebugUtilsMessengerCreateInfoEXT));
-            *pMessengers++ = (VkDebugUtilsMessengerEXT)(uintptr_t)pInfos++;
-        }
-        pNext = (void *)((VkInstanceCreateInfo *)pNext)->pNext;
-    }
-
-    *num_messengers = n;
-    return VK_SUCCESS;
-}
-
-void util_FreeDebugUtilsMessengerCreateInfos(const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerCreateInfoEXT *infos,
-                                             VkDebugUtilsMessengerEXT *messengers) {
-    loader_free(pAllocator, infos);
-    loader_free(pAllocator, messengers);
-}
-
-VkResult util_CreateDebugUtilsMessengers(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator,
-                                         uint32_t num_messengers, VkDebugUtilsMessengerCreateInfoEXT *infos,
-                                         VkDebugUtilsMessengerEXT *messengers) {
-    VkResult rtn = VK_SUCCESS;
-    for (uint32_t i = 0; i < num_messengers; i++) {
-        rtn = util_CreateDebugUtilsMessenger(inst, &infos[i], pAllocator, messengers[i]);
-        if (rtn != VK_SUCCESS) {
-            for (uint32_t j = 0; j < i; j++) {
-                util_DestroyDebugUtilsMessenger(inst, messengers[j], pAllocator);
+        if (((const VkBaseInStructure *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
+            // Assign a unique handle to each messenger (just use the address of the VkDebugUtilsMessengerCreateInfoEXT)
+            // This is only being used this way due to it being for an 'anonymous' callback during instance creation
+            VkDebugUtilsMessengerEXT messenger_handle = (VkDebugUtilsMessengerEXT)(uintptr_t)pNext;
+            VkResult ret = util_CreateDebugUtilsMessenger(inst, (const VkDebugUtilsMessengerCreateInfoEXT *)pNext, pAllocator,
+                                                          messenger_handle);
+            if (ret != VK_SUCCESS) {
+                return ret;
             }
-            return rtn;
         }
+        pNext = (void *)((VkBaseInStructure *)pNext)->pNext;
     }
-    return rtn;
-}
-
-void util_DestroyDebugUtilsMessengers(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator,
-                                      uint32_t num_messengers, VkDebugUtilsMessengerEXT *messengers) {
-    for (uint32_t i = 0; i < num_messengers; i++) {
-        util_DestroyDebugUtilsMessenger(inst, messengers[i], pAllocator);
-    }
+    return VK_SUCCESS;
 }
 
 static VKAPI_ATTR void VKAPI_CALL debug_utils_SubmitDebugUtilsMessageEXT(
@@ -350,7 +287,7 @@ VKAPI_ATTR void VKAPI_CALL terminator_SubmitDebugUtilsMessageEXT(VkInstance inst
 
 // VK_EXT_debug_report related items
 
-VkResult util_CreateDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
+VkResult util_CreateDebugReportCallback(struct loader_instance *inst, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
                                         const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT callback) {
     VkLayerDbgFunctionNode *pNewDbgFuncNode = NULL;
 
@@ -443,87 +380,23 @@ void util_DestroyDebugReportCallback(struct loader_instance *inst, VkDebugReport
     }
 }
 
-// This utility (used by vkInstanceCreateInfo(), looks at a pNext chain.  It
-// counts any VkDebugReportCallbackCreateInfoEXT structs that it finds.  It
-// then allocates array that can hold that many structs, as well as that many
-// VkDebugReportCallbackEXT handles.  It then copies each
-// VkDebugReportCallbackCreateInfoEXT, and initializes each handle.
-VkResult util_CopyDebugReportCreateInfos(const void *pChain, const VkAllocationCallbacks *pAllocator, uint32_t *num_callbacks,
-                                         VkDebugReportCallbackCreateInfoEXT **infos, VkDebugReportCallbackEXT **callbacks) {
-    uint32_t n = *num_callbacks = 0;
-    VkDebugReportCallbackCreateInfoEXT *pInfos = NULL;
-    VkDebugReportCallbackEXT *pCallbacks = NULL;
-
+VkResult util_CreateDebugReportCallbacks(struct loader_instance *inst, const void *pChain,
+                                         const VkAllocationCallbacks *pAllocator) {
     const void *pNext = pChain;
     while (pNext) {
-        // 1st, count the number VkDebugReportCallbackCreateInfoEXT:
-        if (((VkDebugReportCallbackCreateInfoEXT *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
-            n++;
-        }
-        pNext = (void *)((VkDebugReportCallbackCreateInfoEXT *)pNext)->pNext;
-    }
-    if (n == 0) {
-        return VK_SUCCESS;
-    }
-
-    // 2nd, allocate memory for each VkDebugReportCallbackCreateInfoEXT:
-    pInfos = *infos = ((VkDebugReportCallbackCreateInfoEXT *)loader_alloc(
-        pAllocator, n * sizeof(VkDebugReportCallbackCreateInfoEXT), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
-    if (!pInfos) {
-        return VK_ERROR_OUT_OF_HOST_MEMORY;
-    }
-    // 3rd, allocate memory for a unique handle for each callback:
-
-    pCallbacks = *callbacks = ((VkDebugReportCallbackEXT *)loader_alloc(pAllocator, n * sizeof(VkDebugReportCallbackEXT),
-                                                                        VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
-    if (!pCallbacks) {
-        loader_free(pAllocator, pInfos);
-        return VK_ERROR_OUT_OF_HOST_MEMORY;
-    }
-
-    // 4th, copy each VkDebugReportCallbackCreateInfoEXT for use by
-    // vkDestroyInstance, and assign a unique handle to each callback (just
-    // use the address of the copied VkDebugReportCallbackCreateInfoEXT):
-    pNext = pChain;
-    while (pNext) {
-        if (((VkInstanceCreateInfo *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
-            memcpy(pInfos, pNext, sizeof(VkDebugReportCallbackCreateInfoEXT));
-            *pCallbacks++ = (VkDebugReportCallbackEXT)(uintptr_t)pInfos++;
-        }
-        pNext = (void *)((VkInstanceCreateInfo *)pNext)->pNext;
-    }
-
-    *num_callbacks = n;
-    return VK_SUCCESS;
-}
-
-void util_FreeDebugReportCreateInfos(const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackCreateInfoEXT *infos,
-                                     VkDebugReportCallbackEXT *callbacks) {
-    loader_free(pAllocator, infos);
-    loader_free(pAllocator, callbacks);
-}
-
-VkResult util_CreateDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator,
-                                         uint32_t num_callbacks, VkDebugReportCallbackCreateInfoEXT *infos,
-                                         VkDebugReportCallbackEXT *callbacks) {
-    VkResult rtn = VK_SUCCESS;
-    for (uint32_t i = 0; i < num_callbacks; i++) {
-        rtn = util_CreateDebugReportCallback(inst, &infos[i], pAllocator, callbacks[i]);
-        if (rtn != VK_SUCCESS) {
-            for (uint32_t j = 0; j < i; j++) {
-                util_DestroyDebugReportCallback(inst, callbacks[j], pAllocator);
+        if (((VkBaseInStructure *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
+            // Assign a unique handle to each callback (just use the address of the VkDebugReportCallbackCreateInfoEXT):
+            // This is only being used this way due to it being for an 'anonymous' callback during instance creation
+            VkDebugReportCallbackEXT report_handle = (VkDebugReportCallbackEXT)(uintptr_t)pNext;
+            VkResult ret =
+                util_CreateDebugReportCallback(inst, (const VkDebugReportCallbackCreateInfoEXT *)pNext, pAllocator, report_handle);
+            if (ret != VK_SUCCESS) {
+                return ret;
             }
-            return rtn;
         }
+        pNext = (void *)((VkBaseInStructure *)pNext)->pNext;
     }
-    return rtn;
-}
-
-void util_DestroyDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator, uint32_t num_callbacks,
-                                      VkDebugReportCallbackEXT *callbacks) {
-    for (uint32_t i = 0; i < num_callbacks; i++) {
-        util_DestroyDebugReportCallback(inst, callbacks[i], pAllocator);
-    }
+    return VK_SUCCESS;
 }
 
 static VKAPI_ATTR void VKAPI_CALL debug_utils_DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
@@ -680,12 +553,23 @@ static const VkExtensionProperties debug_utils_extension_info[] = {
     {VK_EXT_DEBUG_UTILS_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_SPEC_VERSION},
 };
 
-void debug_utils_AddInstanceExtensions(const struct loader_instance *inst, struct loader_extension_list *ext_list) {
+void destroy_debug_callbacks_chain(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator) {
+    VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead;
+    VkLayerDbgFunctionNode *pNext = NULL;
+    while (pTrav) {
+        pNext = pTrav->pNext;
+        loader_free_with_instance_fallback(pAllocator, inst, pTrav);
+        pTrav = pNext;
+    }
+    inst->DbgFunctionHead = NULL;
+}
+
+void add_debug_extensions_to_ext_list(const struct loader_instance *inst, struct loader_extension_list *ext_list) {
     loader_add_to_ext_list(inst, ext_list, sizeof(debug_utils_extension_info) / sizeof(VkExtensionProperties),
                            debug_utils_extension_info);
 }
 
-void debug_utils_CreateInstance(struct loader_instance *ptr_instance, const VkInstanceCreateInfo *pCreateInfo) {
+void check_for_enabled_debug_extensions(struct loader_instance *ptr_instance, const VkInstanceCreateInfo *pCreateInfo) {
     for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0) {
             ptr_instance->enabled_known_extensions.ext_debug_report = 1;
@@ -695,7 +579,7 @@ void debug_utils_CreateInstance(struct loader_instance *ptr_instance, const VkIn
     }
 }
 
-bool debug_utils_InstanceGpa(struct loader_instance *ptr_instance, const char *name, void **addr) {
+bool debug_extensions_InstanceGpa(struct loader_instance *ptr_instance, const char *name, void **addr) {
     bool ret_type = false;
 
     *addr = NULL;
index cdf6ec34ef84b66db81e9cd6539a6d44771060d9..dec1108f1afc88822cd4dceabae25ba789200580 100644 (file)
@@ -28,9 +28,9 @@
 
 // General utilities
 
-void debug_utils_AddInstanceExtensions(const struct loader_instance *inst, struct loader_extension_list *ext_list);
-void debug_utils_CreateInstance(struct loader_instance *ptr_instance, const VkInstanceCreateInfo *pCreateInfo);
-bool debug_utils_InstanceGpa(struct loader_instance *ptr_instance, const char *name, void **addr);
+void add_debug_extensions_to_ext_list(const struct loader_instance *inst, struct loader_extension_list *ext_list);
+void check_for_enabled_debug_extensions(struct loader_instance *ptr_instance, const VkInstanceCreateInfo *pCreateInfo);
+bool debug_extensions_InstanceGpa(struct loader_instance *ptr_instance, const char *name, void **addr);
 bool debug_utils_ReportFlagsToAnnotFlags(VkDebugReportFlagsEXT dr_flags, bool default_flag_is_spec,
                                          VkDebugUtilsMessageSeverityFlagBitsEXT *da_severity,
                                          VkDebugUtilsMessageTypeFlagsEXT *da_type);
@@ -41,6 +41,8 @@ bool debug_utils_ReportObjectToAnnotObject(VkDebugReportObjectTypeEXT dr_object_
 bool debug_utils_AnnotObjectToDebugReportObject(const VkDebugUtilsObjectNameInfoEXT *da_object_name_info,
                                                 VkDebugReportObjectTypeEXT *dr_object_type, uint64_t *dr_object_handle);
 
+void destroy_debug_callbacks_chain(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator);
+
 // VK_EXT_debug_utils related items
 
 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugUtilsMessengerEXT(VkInstance instance,
@@ -53,23 +55,10 @@ VKAPI_ATTR void VKAPI_CALL terminator_SubmitDebugUtilsMessageEXT(VkInstance inst
                                                                  VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
                                                                  VkDebugUtilsMessageTypeFlagsEXT messageTypes,
                                                                  const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData);
-VkResult util_CreateDebugUtilsMessenger(struct loader_instance *inst, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
-                                        const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerEXT messenger);
-VkResult util_CreateDebugUtilsMessengers(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator,
-                                         uint32_t num_messengers, VkDebugUtilsMessengerCreateInfoEXT *infos,
-                                         VkDebugUtilsMessengerEXT *messengers);
+VkResult util_CreateDebugUtilsMessengers(struct loader_instance *inst, const void *pChain, const VkAllocationCallbacks *pAllocator);
 VkBool32 util_SubmitDebugUtilsMessageEXT(const struct loader_instance *inst, VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
                                          VkDebugUtilsMessageTypeFlagsEXT messageTypes,
                                          const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData);
-VkResult util_CopyDebugUtilsMessengerCreateInfos(const void *pChain, const VkAllocationCallbacks *pAllocator,
-                                                 uint32_t *num_messengers, VkDebugUtilsMessengerCreateInfoEXT **infos,
-                                                 VkDebugUtilsMessengerEXT **messengers);
-void util_DestroyDebugUtilsMessenger(struct loader_instance *inst, VkDebugUtilsMessengerEXT messenger,
-                                     const VkAllocationCallbacks *pAllocator);
-void util_DestroyDebugUtilsMessengers(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator,
-                                      uint32_t num_messengers, VkDebugUtilsMessengerEXT *messengers);
-void util_FreeDebugUtilsMessengerCreateInfos(const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerCreateInfoEXT *infos,
-                                             VkDebugUtilsMessengerEXT *messengers);
 
 // VK_EXT_debug_report related items
 
@@ -85,18 +74,6 @@ VKAPI_ATTR void VKAPI_CALL terminator_DebugReportMessageEXT(VkInstance instance,
                                                             VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location,
                                                             int32_t msgCode, const char *pLayerPrefix, const char *pMsg);
 
-VkResult util_CreateDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
-                                        const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT callback);
-VkResult util_CreateDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator,
-                                         uint32_t num_callbacks, VkDebugReportCallbackCreateInfoEXT *infos,
-                                         VkDebugReportCallbackEXT *callbacks);
+VkResult util_CreateDebugReportCallbacks(struct loader_instance *inst, const void *pChain, const VkAllocationCallbacks *pAllocator);
 VkBool32 util_DebugReportMessage(const struct loader_instance *inst, VkFlags msgFlags, VkDebugReportObjectTypeEXT objectType,
                                  uint64_t srcObject, size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg);
-VkResult util_CopyDebugReportCreateInfos(const void *pChain, const VkAllocationCallbacks *pAllocator, uint32_t *num_callbacks,
-                                         VkDebugReportCallbackCreateInfoEXT **infos, VkDebugReportCallbackEXT **callbacks);
-void util_DestroyDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackEXT callback,
-                                     const VkAllocationCallbacks *pAllocator);
-void util_DestroyDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator, uint32_t num_callbacks,
-                                      VkDebugReportCallbackEXT *callbacks);
-void util_FreeDebugReportCreateInfos(const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackCreateInfoEXT *infos,
-                                     VkDebugReportCallbackEXT *callbacks);
index 235bacea3fd187bdc1be4c431c1668ad0a806392..13481ca69bcb12b8d1b96a0dfae105486f738d63 100644 (file)
@@ -252,7 +252,7 @@ void *trampoline_get_proc_addr(struct loader_instance *inst, const char *funcNam
 
     // Instance extensions
     void *addr;
-    if (debug_utils_InstanceGpa(inst, funcName, &addr)) return addr;
+    if (debug_extensions_InstanceGpa(inst, funcName, &addr)) return addr;
 
     if (wsi_swapchain_instance_gpa(inst, funcName, &addr)) return addr;
 
index 9e9ec73a22c11db93d357440e3b3f8ae45d5b63d..6dea865fe3f8a1c2854a74e51b9cdfd6c79e6c08 100644 (file)
@@ -1163,7 +1163,7 @@ VkResult loader_get_icd_loader_instance_extensions(const struct loader_instance
     };
 
     // Traverse loader's extensions, adding non-duplicate extensions to the list
-    debug_utils_AddInstanceExtensions(inst, inst_exts);
+    add_debug_extensions_to_ext_list(inst, inst_exts);
 
     static const VkExtensionProperties portability_enumeration_extension_info[] = {
         {VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME, VK_KHR_PORTABILITY_ENUMERATION_SPEC_VERSION}};
@@ -5341,7 +5341,7 @@ out:
         // The clearing should actually be handled by the overall memset of the pInstance structure in the
         // trampoline.
         wsi_create_instance(ptr_instance, pCreateInfo);
-        debug_utils_CreateInstance(ptr_instance, pCreateInfo);
+        check_for_enabled_debug_extensions(ptr_instance, pCreateInfo);
         extensions_create_instance(ptr_instance, pCreateInfo);
     }
 
index 6aa1c99171e3a260ef5a9ebab4050b968f3b2457..7fcfd816db3dd95fddc4c5677dbad69ef4467809 100644 (file)
@@ -282,13 +282,13 @@ struct loader_instance {
     struct loader_extension_list ext_list;  // icds and loaders extensions
     struct loader_instance_extension_enables enabled_known_extensions;
 
+    // Stores debug callbacks - used in the log
     VkLayerDbgFunctionNode *DbgFunctionHead;
-    uint32_t num_tmp_report_callbacks;
-    VkDebugReportCallbackCreateInfoEXT *tmp_report_create_infos;
-    VkDebugReportCallbackEXT *tmp_report_callbacks;
-    uint32_t num_tmp_messengers;
-    VkDebugUtilsMessengerCreateInfoEXT *tmp_messenger_create_infos;
-    VkDebugUtilsMessengerEXT *tmp_messengers;
+
+    // Stores the debug callbacks set during instance creation
+    // These are kept separate because they aren't to be used outside of instance creation and destruction
+    // So they are swapped out at the end of instance creation and swapped in at instance destruction
+    VkLayerDbgFunctionNode *InstanceCreationDeletionDebugFunctionHead;
 
     VkAllocationCallbacks alloc_callbacks;
 
@@ -452,4 +452,4 @@ struct loader_phys_dev_per_icd {
 struct loader_msg_callback_map_entry {
     VkDebugReportCallbackEXT icd_obj;
     VkDebugReportCallbackEXT loader_obj;
-};
\ No newline at end of file
+};
index 075b939c20f756b2db68a48812b494753f40075b..7c243ed0cb4462bf6e714baddc8f7d2b0236775b 100644 (file)
@@ -434,7 +434,6 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCr
                                                               const VkAllocationCallbacks *pAllocator, VkInstance *pInstance) {
     struct loader_instance *ptr_instance = NULL;
     VkInstance created_instance = VK_NULL_HANDLE;
-    bool loaderLocked = false;
     VkResult res = VK_ERROR_INITIALIZATION_FAILED;
 
     LOADER_PLATFORM_THREAD_ONCE(&once_init, loader_initialize);
@@ -451,7 +450,7 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCr
     }
 
     ptr_instance =
-        (struct loader_instance *)loader_alloc(pAllocator, sizeof(struct loader_instance), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+        (struct loader_instance *)loader_calloc(pAllocator, sizeof(struct loader_instance), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
 
     VkInstanceCreateInfo ici = *pCreateInfo;
 
@@ -461,8 +460,6 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCr
     }
 
     loader_platform_thread_lock_mutex(&loader_lock);
-    loaderLocked = true;
-    memset(ptr_instance, 0, sizeof(struct loader_instance));
     if (pAllocator) {
         ptr_instance->alloc_callbacks = *pAllocator;
     }
@@ -477,56 +474,34 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCr
         ptr_instance->app_api_version.patch = 0;
     }
 
-    // Check the VkInstanceCreateInfoFlags wether to allow the portability enumeration flag
-    if ((pCreateInfo->flags & VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR) == 1) {
-        // Make sure the extension has been enabled
-        for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
-            if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME) == 0) {
-                ptr_instance->portability_enumeration_enabled = true;
-                loader_log(ptr_instance, VULKAN_LOADER_INFO_BIT, 0,
-                           "Portability enumeration bit was set, enumerating portability drivers.");
-            }
-        }
-    }
-
     // Look for one or more VK_EXT_debug_report or VK_EXT_debug_utils create info structures
     // and setup a callback(s) for each one found.
-    ptr_instance->num_tmp_report_callbacks = 0;
-    ptr_instance->tmp_report_create_infos = NULL;
-    ptr_instance->tmp_report_callbacks = NULL;
-    ptr_instance->num_tmp_messengers = 0;
-    ptr_instance->tmp_messenger_create_infos = NULL;
-    ptr_instance->tmp_messengers = NULL;
 
     // Handle cases of VK_EXT_debug_utils
-    if (util_CopyDebugUtilsMessengerCreateInfos(pCreateInfo->pNext, pAllocator, &ptr_instance->num_tmp_messengers,
-                                                &ptr_instance->tmp_messenger_create_infos, &ptr_instance->tmp_messengers)) {
-        // One or more were found, but allocation failed.  Therefore, clean up and fail this function:
-        res = VK_ERROR_OUT_OF_HOST_MEMORY;
+    // Setup the temporary messenger(s) here to catch early issues:
+    res = util_CreateDebugUtilsMessengers(ptr_instance, pCreateInfo->pNext, pAllocator);
+    if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
+        // Failure of setting up one or more of the messenger.
         goto out;
-    } else if (ptr_instance->num_tmp_messengers > 0) {
-        // Setup the temporary messenger(s) here to catch early issues:
-        if (util_CreateDebugUtilsMessengers(ptr_instance, pAllocator, ptr_instance->num_tmp_messengers,
-                                            ptr_instance->tmp_messenger_create_infos, ptr_instance->tmp_messengers)) {
-            // Failure of setting up one or more of the messenger.  Therefore, clean up and fail this function:
-            res = VK_ERROR_OUT_OF_HOST_MEMORY;
-            goto out;
-        }
     }
 
     // Handle cases of VK_EXT_debug_report
-    if (util_CopyDebugReportCreateInfos(pCreateInfo->pNext, pAllocator, &ptr_instance->num_tmp_report_callbacks,
-                                        &ptr_instance->tmp_report_create_infos, &ptr_instance->tmp_report_callbacks)) {
-        // One or more were found, but allocation failed.  Therefore, clean up and fail this function:
-        res = VK_ERROR_OUT_OF_HOST_MEMORY;
+    // Setup the temporary callback(s) here to catch early issues:
+    res = util_CreateDebugReportCallbacks(ptr_instance, pCreateInfo->pNext, pAllocator);
+    if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
+        // Failure of setting up one or more of the callback.
         goto out;
-    } else if (ptr_instance->num_tmp_report_callbacks > 0) {
-        // Setup the temporary callback(s) here to catch early issues:
-        if (util_CreateDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_report_callbacks,
-                                            ptr_instance->tmp_report_create_infos, ptr_instance->tmp_report_callbacks)) {
-            // Failure of setting up one or more of the callback.  Therefore, clean up and fail this function:
-            res = VK_ERROR_OUT_OF_HOST_MEMORY;
-            goto out;
+    }
+
+    // Check the VkInstanceCreateInfoFlags wether to allow the portability enumeration flag
+    if ((pCreateInfo->flags & VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR) == 1) {
+        // Make sure the extension has been enabled
+        for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
+            if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME) == 0) {
+                ptr_instance->portability_enumeration_enabled = true;
+                loader_log(ptr_instance, VULKAN_LOADER_INFO_BIT, 0,
+                           "Portability enumeration bit was set, enumerating portability drivers.");
+            }
         }
     }
 
@@ -617,7 +592,7 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCr
         // This is why we don't clear inside of these function calls.
         // The clearing should actually be handled by the overall memset of the pInstance structure above.
         wsi_create_instance(ptr_instance, &ici);
-        debug_utils_CreateInstance(ptr_instance, &ici);
+        check_for_enabled_debug_extensions(ptr_instance, &ici);
         extensions_create_instance(ptr_instance, &ici);
 
         *pInstance = (VkInstance)ptr_instance;
@@ -636,26 +611,15 @@ out:
 
     if (NULL != ptr_instance) {
         if (res != VK_SUCCESS) {
+            // error path, should clean everything up
             if (loader.instances == ptr_instance) {
                 loader.instances = ptr_instance->next;
             }
             if (NULL != ptr_instance->disp) {
                 loader_instance_heap_free(ptr_instance, ptr_instance->disp);
             }
-            if (ptr_instance->num_tmp_report_callbacks > 0) {
-                // Remove temporary VK_EXT_debug_report items
-                util_DestroyDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_report_callbacks,
-                                                 ptr_instance->tmp_report_callbacks);
-                util_FreeDebugReportCreateInfos(pAllocator, ptr_instance->tmp_report_create_infos,
-                                                ptr_instance->tmp_report_callbacks);
-            }
-            if (ptr_instance->num_tmp_messengers > 0) {
-                // Remove temporary VK_EXT_debug_utils items
-                util_DestroyDebugUtilsMessengers(ptr_instance, pAllocator, ptr_instance->num_tmp_messengers,
-                                                 ptr_instance->tmp_messengers);
-                util_FreeDebugUtilsMessengerCreateInfos(pAllocator, ptr_instance->tmp_messenger_create_infos,
-                                                        ptr_instance->tmp_messengers);
-            }
+            // Remove any created VK_EXT_debug_report or VK_EXT_debug_utils items
+            destroy_debug_callbacks_chain(ptr_instance, pAllocator);
 
             if (NULL != ptr_instance->expanded_activated_layer_list.list) {
                 loader_deactivate_layers(ptr_instance, NULL, &ptr_instance->expanded_activated_layer_list);
@@ -670,16 +634,11 @@ out:
 
             loader_instance_heap_free(ptr_instance, ptr_instance);
         } else {
-            // Remove temporary VK_EXT_debug_report or VK_EXT_debug_utils items
-            util_DestroyDebugUtilsMessengers(ptr_instance, pAllocator, ptr_instance->num_tmp_messengers,
-                                             ptr_instance->tmp_messengers);
-            util_DestroyDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_report_callbacks,
-                                             ptr_instance->tmp_report_callbacks);
-        }
-
-        if (loaderLocked) {
-            loader_platform_thread_unlock_mutex(&loader_lock);
+            // success path, swap out created debug callbacks out so they aren't used until instance destruction
+            ptr_instance->InstanceCreationDeletionDebugFunctionHead = ptr_instance->DbgFunctionHead;
+            ptr_instance->DbgFunctionHead = NULL;
         }
+        loader_platform_thread_unlock_mutex(&loader_lock);
     }
 
     return res;
@@ -688,8 +647,6 @@ out:
 LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
     const VkLayerInstanceDispatchTable *disp;
     struct loader_instance *ptr_instance = NULL;
-    bool callback_setup = false;
-    bool messenger_setup = false;
 
     if (instance == VK_NULL_HANDLE) {
         return;
@@ -708,21 +665,12 @@ LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance,
         ptr_instance->alloc_callbacks = *pAllocator;
     }
 
-    if (ptr_instance->num_tmp_messengers > 0) {
-        // Setup the temporary VK_EXT_debug_utils messenger(s) here to catch cleanup issues:
-        if (!util_CreateDebugUtilsMessengers(ptr_instance, pAllocator, ptr_instance->num_tmp_messengers,
-                                             ptr_instance->tmp_messenger_create_infos, ptr_instance->tmp_messengers)) {
-            messenger_setup = true;
-        }
-    }
+    // Remove any callbacks that weren't cleaned up by the application
+    destroy_debug_callbacks_chain(ptr_instance, pAllocator);
 
-    if (ptr_instance->num_tmp_report_callbacks > 0) {
-        // Setup the temporary VK_EXT_debug_report callback(s) here to catch cleanup issues:
-        if (!util_CreateDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_report_callbacks,
-                                             ptr_instance->tmp_report_create_infos, ptr_instance->tmp_report_callbacks)) {
-            callback_setup = true;
-        }
-    }
+    // Swap in the debug callbacks created during instance creation
+    ptr_instance->DbgFunctionHead = ptr_instance->InstanceCreationDeletionDebugFunctionHead;
+    ptr_instance->InstanceCreationDeletionDebugFunctionHead = NULL;
 
     disp = loader_get_instance_layer_dispatch(instance);
     disp->DestroyInstance(ptr_instance->instance, pAllocator);
@@ -741,22 +689,8 @@ LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance,
         loader_instance_heap_free(ptr_instance, ptr_instance->phys_devs_tramp);
     }
 
-    if (messenger_setup) {
-        loader_log(ptr_instance, VULKAN_LOADER_INFO_BIT, 0,
-                   "vkDestroyInstance: destroying temporary instance debug util messenger");
-
-        util_DestroyDebugUtilsMessengers(ptr_instance, pAllocator, ptr_instance->num_tmp_messengers, ptr_instance->tmp_messengers);
-        util_FreeDebugUtilsMessengerCreateInfos(pAllocator, ptr_instance->tmp_messenger_create_infos, ptr_instance->tmp_messengers);
-    }
-
-    if (callback_setup) {
-        loader_log(ptr_instance, VULKAN_LOADER_INFO_BIT, 0,
-                   "vkDestroyInstance: destroying temporary instance debug report callback");
-
-        util_DestroyDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_report_callbacks,
-                                         ptr_instance->tmp_report_callbacks);
-        util_FreeDebugReportCreateInfos(pAllocator, ptr_instance->tmp_report_create_infos, ptr_instance->tmp_report_callbacks);
-    }
+    // Destroy the debug callbacks created during instance creation
+    destroy_debug_callbacks_chain(ptr_instance, pAllocator);
 
     loader_instance_heap_free(ptr_instance, ptr_instance->disp);
     loader_instance_heap_free(ptr_instance, ptr_instance);
index 3dc905329ca59d976756939488f317be8076c8a4..1cefbb8c5d6255732e1110527145454c374f4430 100644 (file)
@@ -179,34 +179,6 @@ TEST_F(CreateDestroyInstanceReport, WarnInCreate) {
     ASSERT_EQ(true, message_found);
 }
 
-// Test report (error/warning) created in vkCreateInstance with info in vkDestroyInstance
-TEST_F(CreateDestroyInstanceReport, InfoInDestroyIgnored) {
-    expected_message = "destroying temporary instance debug report callback";
-    expected_object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT;
-    expected_flag = VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
-
-    VkInstance inst = VK_NULL_HANDLE;
-    ASSERT_EQ(VK_SUCCESS, CreateReportInstance(VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT, &inst));
-    env->vulkan_functions.vkDestroyInstance(inst, nullptr);
-
-    // Should be not be found
-    ASSERT_EQ(false, message_found);
-}
-
-// Test report (info) created in vkCreateInstance with info in vkDestroyInstance
-TEST_F(CreateDestroyInstanceReport, InfoInDestroy) {
-    expected_message = "destroying temporary instance debug report callback";
-    expected_object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT;
-    expected_flag = VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
-
-    VkInstance inst = VK_NULL_HANDLE;
-    ASSERT_EQ(VK_SUCCESS, CreateReportInstance(VK_DEBUG_REPORT_INFORMATION_BIT_EXT, &inst));
-    env->vulkan_functions.vkDestroyInstance(inst, nullptr);
-
-    // Message should be found
-    ASSERT_EQ(true, message_found);
-}
-
 // Test report (error/warning) created in vkCreateInstance with error in vkEnumeratePhysicalDevices.
 // This should not be logged because we have only defined the debug report logging for vkCreateInstance
 // and vkDestroyInstance.
@@ -554,62 +526,6 @@ TEST_F(CreateDestroyInstanceMessenger, WarnInCreate) {
     ASSERT_EQ(true, message_found);
 }
 
-// Test debug utils error/warn created in vkCreateInstance with info in vkDestroyInstance
-TEST_F(CreateDestroyInstanceMessenger, DestroyInfoIgnoredSeverity) {
-    expected_message = "destroying temporary instance debug util messenger";
-    expected_object_type = VK_OBJECT_TYPE_INSTANCE;
-    expected_message_flags = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
-    expected_severity_flags = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
-
-    VkApplicationInfo app_info;
-    app_info.apiVersion = VK_MAKE_API_VERSION(1, 1, 0, 0);
-
-    VkInstance inst = VK_NULL_HANDLE;
-    ASSERT_EQ(VK_SUCCESS,
-              CreateUtilsInstance(VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT,
-                                  VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT,
-                                  &inst, &app_info));
-    env->vulkan_functions.vkDestroyInstance(inst, nullptr);
-
-    ASSERT_EQ(false, message_found);
-}
-
-// Test debug utils info/performance created in vkCreateInstance with info/general in vkDestroyInstance
-TEST_F(CreateDestroyInstanceMessenger, DestroyInfoIgnoredType) {
-    expected_message = "destroying temporary instance debug util messenger";
-    expected_object_type = VK_OBJECT_TYPE_INSTANCE;
-    expected_message_flags = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
-    expected_severity_flags = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
-
-    VkApplicationInfo app_info;
-    app_info.apiVersion = VK_MAKE_API_VERSION(1, 1, 0, 0);
-
-    VkInstance inst = VK_NULL_HANDLE;
-    ASSERT_EQ(VK_SUCCESS, CreateUtilsInstance(VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT,
-                                              VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT, &inst, &app_info));
-    env->vulkan_functions.vkDestroyInstance(inst, nullptr);
-
-    ASSERT_EQ(false, message_found);
-}
-
-// Test debug utils info/general created in vkCreateInstance with info/general in vkDestroyInstance
-TEST_F(CreateDestroyInstanceMessenger, DestroyInfo) {
-    expected_message = "destroying temporary instance debug util messenger";
-    expected_object_type = VK_OBJECT_TYPE_INSTANCE;
-    expected_message_flags = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
-    expected_severity_flags = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
-
-    VkApplicationInfo app_info;
-    app_info.apiVersion = VK_MAKE_API_VERSION(1, 1, 0, 0);
-
-    VkInstance inst = VK_NULL_HANDLE;
-    ASSERT_EQ(VK_SUCCESS, CreateUtilsInstance(VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT,
-                                              VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT, &inst, &app_info));
-    env->vulkan_functions.vkDestroyInstance(inst, nullptr);
-
-    ASSERT_EQ(true, message_found);
-}
-
 // Test debug utils error created in vkCreateInstance with error in vkEnumeratePhysicalDevices.
 // This should not be logged because we have only defined the debug utils logging for vkCreateInstance
 // and vkDestroyInstance.