From ff354e57e6da2c65b908e33e003f4db33f4a9f6e Mon Sep 17 00:00:00 2001 From: baldurk Date: Mon, 1 Apr 2019 14:25:49 +0100 Subject: [PATCH] Add handling for EXT_debug_utils for gathering debug messages * Where possible we use it as we expect potentially better message formatting & more info we can use in future --- renderdoc/driver/vulkan/vk_core.cpp | 163 +++++++++--------- renderdoc/driver/vulkan/vk_core.h | 27 +-- .../vulkan/wrappers/vk_device_funcs.cpp | 147 ++++++++++++++-- 3 files changed, 226 insertions(+), 111 deletions(-) diff --git a/renderdoc/driver/vulkan/vk_core.cpp b/renderdoc/driver/vulkan/vk_core.cpp index 93f741513..2ad9d7b17 100644 --- a/renderdoc/driver/vulkan/vk_core.cpp +++ b/renderdoc/driver/vulkan/vk_core.cpp @@ -146,7 +146,7 @@ WrappedVulkan::WrappedVulkan() : m_RenderState(this, &m_CreationInfo) m_Device = VK_NULL_HANDLE; m_Queue = VK_NULL_HANDLE; m_QueueFamilyIdx = 0; - m_DbgMsgCallback = VK_NULL_HANDLE; + m_DbgReportCallback = VK_NULL_HANDLE; m_HeaderChunk = NULL; @@ -3232,31 +3232,9 @@ void WrappedVulkan::AddDebugMessage(DebugMessage msg) m_DebugMessages.push_back(msg); } -VkBool32 WrappedVulkan::DebugCallback(VkDebugReportFlagsEXT flags, - VkDebugReportObjectTypeEXT objectType, uint64_t object, - size_t location, int32_t messageCode, - const char *pLayerPrefix, const char *pMessage) +VkBool32 WrappedVulkan::DebugCallback(MessageSeverity severity, MessageCategory category, + int messageCode, const char *pMessageId, const char *pMessage) { - bool isDS = false, isMEM = false, isSC = false, isOBJ = false, isSWAP = false, isDL = false, - isIMG = false, isPARAM = false; - - if(!strcmp(pLayerPrefix, "DS")) - isDS = true; - else if(!strcmp(pLayerPrefix, "MEM")) - isMEM = true; - else if(!strcmp(pLayerPrefix, "SC")) - isSC = true; - else if(!strcmp(pLayerPrefix, "OBJTRACK")) - isOBJ = true; - else if(!strcmp(pLayerPrefix, "SWAP_CHAIN") || !strcmp(pLayerPrefix, "Swapchain")) - isSWAP = true; - else if(!strcmp(pLayerPrefix, "DL")) - isDL = true; - else if(!strcmp(pLayerPrefix, "Image")) - isIMG = true; - else if(!strcmp(pLayerPrefix, "PARAMCHECK") || !strcmp(pLayerPrefix, "ParameterValidation")) - isPARAM = true; - { ScopedDebugMessageSink *sink = GetDebugMessageSink(); @@ -3265,9 +3243,9 @@ VkBool32 WrappedVulkan::DebugCallback(VkDebugReportFlagsEXT flags, DebugMessage msg; msg.eventId = 0; - msg.category = MessageCategory::Miscellaneous; + msg.category = category; msg.description = pMessage; - msg.severity = MessageSeverity::Low; + msg.severity = severity; msg.messageID = messageCode; msg.source = MessageSource::API; @@ -3282,75 +3260,102 @@ VkBool32 WrappedVulkan::DebugCallback(VkDebugReportFlagsEXT flags, msg.eventId = it->eventId; } - if(flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) - msg.severity = MessageSeverity::Info; - else if(flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) - msg.severity = MessageSeverity::Low; - else if(flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) - msg.severity = MessageSeverity::Medium; - else if(flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) - msg.severity = MessageSeverity::High; - - if(flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) - msg.category = MessageCategory::Performance; - else if(isDS) - msg.category = MessageCategory::Execution; - else if(isMEM) - msg.category = MessageCategory::Resource_Manipulation; - else if(isSC) - msg.category = MessageCategory::Shaders; - else if(isOBJ) - msg.category = MessageCategory::State_Setting; - else if(isSWAP) - msg.category = MessageCategory::Miscellaneous; - else if(isDL) - msg.category = MessageCategory::Portability; - else if(isIMG) - msg.category = MessageCategory::State_Creation; - else if(isPARAM) - msg.category = MessageCategory::Miscellaneous; - - if(isIMG || isPARAM) - msg.source = MessageSource::IncorrectAPIUse; - sink->msgs.push_back(msg); } } { - // All access mask/barrier messages. - // These are just too spammy/false positive/unreliable to keep - if(isDS && messageCode == 10) - return false; - // ignore perf warnings - if(flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) - return false; - - // Memory is aliased between image and buffer - // ignore memory aliasing warning - we make use of the memory in disjoint ways - // and copy image data over separately, so our use is safe - // no location set for this one, so ignore by code (maybe too coarse) - if(isMEM && messageCode == 3) - return false; - - // Cannot read invalid region of memory - // The validation layers can't track simultaneous use of the same memory in multiple buffers, so - // misreports any buffer which was filled by initial states (whole-memory buffer copies). - if(isMEM && messageCode == 15) + if(category == MessageCategory::Performance) return false; // Non-linear image is aliased with linear buffer // Not an error, the validation layers complain at our whole-mem bufs - if(strstr(pMessage, "InvalidAliasing")) + if(strstr(pMessageId, "InvalidAliasing") || strstr(pMessage, "InvalidAliasing")) return false; - RDCWARN("[%s:%u/%d] %s", pLayerPrefix, (uint32_t)location, messageCode, pMessage); + RDCWARN("[%s] %s", pMessageId, pMessage); } return false; } +VkBool32 VKAPI_PTR WrappedVulkan::DebugReportCallbackStatic(VkDebugReportFlagsEXT flags, + VkDebugReportObjectTypeEXT objectType, + uint64_t object, size_t location, + int32_t messageCode, + const char *pLayerPrefix, + const char *pMessage, void *pUserData) +{ + MessageSeverity severity = MessageSeverity::Low; + + if(flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) + severity = MessageSeverity::High; + else if(flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) + severity = MessageSeverity::Medium; + else if(flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) + severity = MessageSeverity::Low; + else if(flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) + severity = MessageSeverity::Info; + + MessageCategory category = MessageCategory::Miscellaneous; + + if(flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) + category = MessageCategory::Performance; + + return ((WrappedVulkan *)pUserData) + ->DebugCallback(severity, category, messageCode, pLayerPrefix, pMessage); +} + +VkBool32 VKAPI_PTR WrappedVulkan::DebugUtilsCallbackStatic( + VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageTypes, + const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, void *pUserData) +{ + MessageSeverity severity = MessageSeverity::Low; + + if(messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) + severity = MessageSeverity::High; + else if(messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) + severity = MessageSeverity::Medium; + else if(messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) + severity = MessageSeverity::Low; + else if(messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) + severity = MessageSeverity::Info; + + MessageCategory category = MessageCategory::Miscellaneous; + + if(messageTypes & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) + category = MessageCategory::Performance; + + std::string msgid; + + const char *pMessageId = pCallbackData->pMessageIdName; + int messageCode = pCallbackData->messageIdNumber; + + if(messageCode == 0 && pMessageId && !strncmp(pMessageId, "VUID", 4)) + { + const char *c = pMessageId + strlen(pMessageId) - 1; + int mult = 1; + + while(c > pMessageId && *c >= '0' && *c <= '9') + { + mult *= 10; + messageCode += mult * int(*c - '0'); + c--; + } + } + + if(!pMessageId) + { + msgid = StringFormat::Fmt("%d", pCallbackData->messageIdNumber); + pMessageId = msgid.c_str(); + } + + return ((WrappedVulkan *)pUserData) + ->DebugCallback(severity, category, messageCode, pMessageId, pCallbackData->pMessage); +} + bool WrappedVulkan::HasNonMarkerEvents(ResourceId cmdBuffer) { for(const APIEvent &ev : m_BakedCmdBufferInfo[m_LastCmdBufferID].curEvents) diff --git a/renderdoc/driver/vulkan/vk_core.h b/renderdoc/driver/vulkan/vk_core.h index b4e235815..f120eb9be 100644 --- a/renderdoc/driver/vulkan/vk_core.h +++ b/renderdoc/driver/vulkan/vk_core.h @@ -367,7 +367,8 @@ private: // the instance corresponding to this WrappedVulkan VkInstance m_Instance; // the instance's dbg msg callback handle - VkDebugReportCallbackEXT m_DbgMsgCallback; + VkDebugReportCallbackEXT m_DbgReportCallback; + VkDebugUtilsMessengerEXT m_DbgUtilsCallback; // the physical device we created m_Device with VkPhysicalDevice m_PhysicalDevice; // the device used for our own command buffer work @@ -844,19 +845,19 @@ private: WrappedVulkan(const WrappedVulkan &); WrappedVulkan &operator=(const WrappedVulkan &); - VkBool32 DebugCallback(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, - uint64_t object, size_t location, int32_t messageCode, - const char *pLayerPrefix, const char *pMessage); + VkBool32 DebugCallback(MessageSeverity severity, MessageCategory category, int messageCode, + const char *pMessageId, const char *pMessage); - static VkBool32 VKAPI_PTR DebugCallbackStatic(VkDebugReportFlagsEXT flags, - VkDebugReportObjectTypeEXT objectType, - uint64_t object, size_t location, - int32_t messageCode, const char *pLayerPrefix, - const char *pMessage, void *pUserData) - { - return ((WrappedVulkan *)pUserData) - ->DebugCallback(flags, objectType, object, location, messageCode, pLayerPrefix, pMessage); - } + static VkBool32 VKAPI_PTR DebugUtilsCallbackStatic( + VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageTypes, + const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, void *pUserData); + + static VkBool32 VKAPI_PTR DebugReportCallbackStatic(VkDebugReportFlagsEXT flags, + VkDebugReportObjectTypeEXT objectType, + uint64_t object, size_t location, + int32_t messageCode, const char *pLayerPrefix, + const char *pMessage, void *pUserData); void AddFrameTerminator(uint64_t queueMarkerTag); public: diff --git a/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp index 958df6115..e8c9e83b5 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp @@ -267,10 +267,17 @@ ReplayStatus WrappedVulkan::Initialise(VkInitParams ¶ms, uint64_t sectionVer } } - // we always want this extension if it's available, and not already enabled - if(supportedExtensions.find(VK_EXT_DEBUG_REPORT_EXTENSION_NAME) != supportedExtensions.end() && + // we always want debug extensions if it available, and not already enabled + if(supportedExtensions.find(VK_EXT_DEBUG_UTILS_EXTENSION_NAME) != supportedExtensions.end() && std::find(params.Extensions.begin(), params.Extensions.end(), - VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == params.Extensions.end()) + VK_EXT_DEBUG_UTILS_EXTENSION_NAME) == params.Extensions.end()) + { + RDCLOG("Enabling VK_EXT_debug_utils"); + params.Extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + } + else if(supportedExtensions.find(VK_EXT_DEBUG_REPORT_EXTENSION_NAME) != supportedExtensions.end() && + std::find(params.Extensions.begin(), params.Extensions.end(), + VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == params.Extensions.end()) { RDCLOG("Enabling VK_EXT_debug_report"); params.Extensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); @@ -300,6 +307,36 @@ ReplayStatus WrappedVulkan::Initialise(VkInitParams ¶ms, uint64_t sectionVer m_Instance = VK_NULL_HANDLE; + VkValidationFeaturesEXT featuresEXT = {VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT}; + VkValidationFeatureDisableEXT disableFeatures[] = {VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT}; + featuresEXT.disabledValidationFeatureCount = ARRAY_COUNT(disableFeatures); + featuresEXT.pDisabledValidationFeatures = disableFeatures; + + VkValidationFlagsEXT flagsEXT = {VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT}; + VkValidationCheckEXT disableChecks[] = {VK_VALIDATION_CHECK_SHADERS_EXT}; + flagsEXT.disabledValidationCheckCount = ARRAY_COUNT(disableChecks); + flagsEXT.pDisabledValidationChecks = disableChecks; + + if(supportedExtensions.find(VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME) != supportedExtensions.end() && + std::find(params.Extensions.begin(), params.Extensions.end(), + VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME) == params.Extensions.end()) + { + RDCLOG("Enabling VK_EXT_validation_features"); + params.Extensions.push_back(VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME); + + instinfo.pNext = &featuresEXT; + } + else if(supportedExtensions.find(VK_EXT_VALIDATION_FLAGS_EXTENSION_NAME) != + supportedExtensions.end() && + std::find(params.Extensions.begin(), params.Extensions.end(), + VK_EXT_VALIDATION_FLAGS_EXTENSION_NAME) == params.Extensions.end()) + { + RDCLOG("Enabling VK_EXT_validation_flags"); + params.Extensions.push_back(VK_EXT_VALIDATION_FLAGS_EXTENSION_NAME); + + instinfo.pNext = &flagsEXT; + } + VkResult ret = GetInstanceDispatchTable(NULL)->CreateInstance(&instinfo, NULL, &m_Instance); #undef CheckExt @@ -336,25 +373,40 @@ ReplayStatus WrappedVulkan::Initialise(VkInitParams ¶ms, uint64_t sectionVer InitInstanceExtensionTables(m_Instance, &m_EnabledExtensions); - m_DbgMsgCallback = VK_NULL_HANDLE; + m_DbgReportCallback = VK_NULL_HANDLE; + m_DbgUtilsCallback = VK_NULL_HANDLE; m_PhysicalDevice = VK_NULL_HANDLE; m_Device = VK_NULL_HANDLE; m_QueueFamilyIdx = ~0U; m_PrevQueue = m_Queue = VK_NULL_HANDLE; m_InternalCmds.Reset(); - if(ObjDisp(m_Instance)->CreateDebugReportCallbackEXT) + if(ObjDisp(m_Instance)->CreateDebugUtilsMessengerEXT) + { + VkDebugUtilsMessengerCreateInfoEXT debugInfo = {}; + debugInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; + debugInfo.pfnUserCallback = &DebugUtilsCallbackStatic; + debugInfo.pUserData = this; + debugInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; + debugInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; + + ObjDisp(m_Instance) + ->CreateDebugUtilsMessengerEXT(Unwrap(m_Instance), &debugInfo, NULL, &m_DbgUtilsCallback); + } + else if(ObjDisp(m_Instance)->CreateDebugReportCallbackEXT) { VkDebugReportCallbackCreateInfoEXT debugInfo = {}; debugInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT; - debugInfo.pNext = NULL; - debugInfo.pfnCallback = &DebugCallbackStatic; + debugInfo.pfnCallback = &DebugReportCallbackStatic; debugInfo.pUserData = this; debugInfo.flags = VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT | VK_DEBUG_REPORT_ERROR_BIT_EXT; ObjDisp(m_Instance) - ->CreateDebugReportCallbackEXT(Unwrap(m_Instance), &debugInfo, NULL, &m_DbgMsgCallback); + ->CreateDebugReportCallbackEXT(Unwrap(m_Instance), &debugInfo, NULL, &m_DbgReportCallback); } uint32_t count = 0; @@ -439,19 +491,42 @@ VkResult WrappedVulkan::vkCreateInstance(const VkInstanceCreateInfo *pCreateInfo report = (VkDebugReportCallbackCreateInfoEXT *)report->pNext; } + // or debug utils callbacks + VkDebugUtilsMessengerCreateInfoEXT *messenger = + (VkDebugUtilsMessengerCreateInfoEXT *)pCreateInfo->pNext; + + VkDebugUtilsMessengerCallbackDataEXT messengerData = {}; + + messengerData.messageIdNumber = 1; + messengerData.pMessageIdName = NULL; + messengerData.pMessage = "RenderDoc does not support a requested instance extension."; + messengerData.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT; + + while(messenger) + { + if(messenger && messenger->sType == VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) + messenger->pfnUserCallback(VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, + VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT, &messengerData, + messenger->pUserData); + + messenger = (VkDebugUtilsMessengerCreateInfoEXT *)messenger->pNext; + } + return VK_ERROR_EXTENSION_NOT_PRESENT; } } const char **addedExts = new const char *[modifiedCreateInfo.enabledExtensionCount + 1]; - bool hasDebugReport = false; + bool hasDebugReport = false, hasDebugUtils = false; for(uint32_t i = 0; i < modifiedCreateInfo.enabledExtensionCount; i++) { addedExts[i] = modifiedCreateInfo.ppEnabledExtensionNames[i]; if(!strcmp(addedExts[i], VK_EXT_DEBUG_REPORT_EXTENSION_NAME)) hasDebugReport = true; + if(!strcmp(addedExts[i], VK_EXT_DEBUG_UTILS_EXTENSION_NAME)) + hasDebugUtils = true; } std::vector supportedExts; @@ -479,8 +554,19 @@ VkResult WrappedVulkan::vkCreateInstance(const VkInstanceCreateInfo *pCreateInfo "Couldn't load vkEnumerateInstanceExtensionProperties in vkCreateInstance to enumerate " "instance extensions"); - // always enable debug report, if it's available - if(!hasDebugReport) + // always enable debug report/utils, if it's available + if(!hasDebugUtils) + { + for(const VkExtensionProperties &ext : supportedExts) + { + if(!strcmp(ext.extensionName, VK_EXT_DEBUG_UTILS_EXTENSION_NAME)) + { + addedExts[modifiedCreateInfo.enabledExtensionCount++] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME; + break; + } + } + } + else if(!hasDebugReport) { for(const VkExtensionProperties &ext : supportedExts) { @@ -595,25 +681,41 @@ VkResult WrappedVulkan::vkCreateInstance(const VkInstanceCreateInfo *pCreateInfo RenderDoc::Inst().AddDeviceFrameCapturer(LayerDisp(m_Instance), this); - m_DbgMsgCallback = VK_NULL_HANDLE; + m_DbgReportCallback = VK_NULL_HANDLE; + m_DbgUtilsCallback = VK_NULL_HANDLE; m_PhysicalDevice = VK_NULL_HANDLE; m_Device = VK_NULL_HANDLE; m_QueueFamilyIdx = ~0U; m_PrevQueue = m_Queue = VK_NULL_HANDLE; m_InternalCmds.Reset(); - if(ObjDisp(m_Instance)->CreateDebugReportCallbackEXT) + if(ObjDisp(m_Instance)->CreateDebugUtilsMessengerEXT) + { + VkDebugUtilsMessengerCreateInfoEXT debugInfo = {}; + debugInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; + debugInfo.pfnUserCallback = &DebugUtilsCallbackStatic; + debugInfo.pUserData = this; + debugInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; + debugInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; + + ObjDisp(m_Instance) + ->CreateDebugUtilsMessengerEXT(Unwrap(m_Instance), &debugInfo, NULL, &m_DbgUtilsCallback); + } + else if(ObjDisp(m_Instance)->CreateDebugReportCallbackEXT) { VkDebugReportCallbackCreateInfoEXT debugInfo = {}; debugInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT; debugInfo.pNext = NULL; - debugInfo.pfnCallback = &DebugCallbackStatic; + debugInfo.pfnCallback = &DebugReportCallbackStatic; debugInfo.pUserData = this; debugInfo.flags = VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT | VK_DEBUG_REPORT_ERROR_BIT_EXT; ObjDisp(m_Instance) - ->CreateDebugReportCallbackEXT(Unwrap(m_Instance), &debugInfo, NULL, &m_DbgMsgCallback); + ->CreateDebugReportCallbackEXT(Unwrap(m_Instance), &debugInfo, NULL, &m_DbgReportCallback); } if(ret == VK_SUCCESS) @@ -689,8 +791,12 @@ void WrappedVulkan::Shutdown() SAFE_DELETE(m_ShaderCache); if(m_Instance && ObjDisp(m_Instance)->DestroyDebugReportCallbackEXT && - m_DbgMsgCallback != VK_NULL_HANDLE) - ObjDisp(m_Instance)->DestroyDebugReportCallbackEXT(Unwrap(m_Instance), m_DbgMsgCallback, NULL); + m_DbgReportCallback != VK_NULL_HANDLE) + ObjDisp(m_Instance)->DestroyDebugReportCallbackEXT(Unwrap(m_Instance), m_DbgReportCallback, NULL); + + if(m_Instance && ObjDisp(m_Instance)->DestroyDebugUtilsMessengerEXT && + m_DbgUtilsCallback != VK_NULL_HANDLE) + ObjDisp(m_Instance)->DestroyDebugUtilsMessengerEXT(Unwrap(m_Instance), m_DbgUtilsCallback, NULL); // need to store the unwrapped device and instance to destroy the // API object after resource manager shutdown @@ -729,8 +835,11 @@ void WrappedVulkan::vkDestroyInstance(VkInstance instance, const VkAllocationCal { RDCASSERT(m_Instance == instance); - if(ObjDisp(m_Instance)->DestroyDebugReportCallbackEXT && m_DbgMsgCallback != VK_NULL_HANDLE) - ObjDisp(m_Instance)->DestroyDebugReportCallbackEXT(Unwrap(m_Instance), m_DbgMsgCallback, NULL); + if(ObjDisp(m_Instance)->DestroyDebugReportCallbackEXT && m_DbgReportCallback != VK_NULL_HANDLE) + ObjDisp(m_Instance)->DestroyDebugReportCallbackEXT(Unwrap(m_Instance), m_DbgReportCallback, NULL); + + if(ObjDisp(m_Instance)->DestroyDebugUtilsMessengerEXT && m_DbgUtilsCallback != VK_NULL_HANDLE) + ObjDisp(m_Instance)->DestroyDebugUtilsMessengerEXT(Unwrap(m_Instance), m_DbgUtilsCallback, NULL); // the device should already have been destroyed, assuming that the // application is well behaved. If not, we just leak.