Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/KhronosGroup/Vulkan-Loader.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles Giessen <charles@lunarg.com>2022-05-25 02:30:23 +0300
committerCharles Giessen <46324611+charles-lunarg@users.noreply.github.com>2022-05-28 02:14:25 +0300
commite52b98e356590627fd87f167d767bdbd5c962fdb (patch)
treedfdefca61a49cae4685ca4213293d2db27bc1b50
parentb1478c3e731c4793ddd2d56c606f5e7aaf94b909 (diff)
Keep allocated debug callbacks until destroy instance
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.
-rw-r--r--loader/debug_utils.c196
-rw-r--r--loader/debug_utils.h37
-rw-r--r--loader/gpa_helper.c2
-rw-r--r--loader/loader.c4
-rw-r--r--loader/loader_common.h14
-rw-r--r--loader/trampoline.c136
-rw-r--r--tests/loader_debug_ext_tests.cpp84
7 files changed, 92 insertions, 381 deletions
diff --git a/loader/debug_utils.c b/loader/debug_utils.c
index 564f3d3ef..fc3f9e01f 100644
--- a/loader/debug_utils.c
+++ b/loader/debug_utils.c
@@ -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;
diff --git a/loader/debug_utils.h b/loader/debug_utils.h
index cdf6ec34e..dec1108f1 100644
--- a/loader/debug_utils.h
+++ b/loader/debug_utils.h
@@ -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);
diff --git a/loader/gpa_helper.c b/loader/gpa_helper.c
index 235bacea3..13481ca69 100644
--- a/loader/gpa_helper.c
+++ b/loader/gpa_helper.c
@@ -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;
diff --git a/loader/loader.c b/loader/loader.c
index 9e9ec73a2..6dea865fe 100644
--- a/loader/loader.c
+++ b/loader/loader.c
@@ -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);
}
diff --git a/loader/loader_common.h b/loader/loader_common.h
index 6aa1c9917..7fcfd816d 100644
--- a/loader/loader_common.h
+++ b/loader/loader_common.h
@@ -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
+};
diff --git a/loader/trampoline.c b/loader/trampoline.c
index 075b939c2..7c243ed0c 100644
--- a/loader/trampoline.c
+++ b/loader/trampoline.c
@@ -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);
diff --git a/tests/loader_debug_ext_tests.cpp b/tests/loader_debug_ext_tests.cpp
index 3dc905329..1cefbb8c5 100644
--- a/tests/loader_debug_ext_tests.cpp
+++ b/tests/loader_debug_ext_tests.cpp
@@ -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.