diff options
| author | Mark Young <marky@lunarg.com> | 2017-11-09 10:37:04 -0700 |
|---|---|---|
| committer | Mike Schuchardt <mikes@lunarg.com> | 2018-03-09 13:54:31 -0700 |
| commit | 4df1d6e03c91637d89d70339674deaece0d7641e (patch) | |
| tree | 274058c2d30cad6b10da6fe6e994da3f22521750 /layers | |
| parent | 9a6be7a671252c15a6b632568cc3f05631f8ef6f (diff) | |
| download | usermoji-4df1d6e03c91637d89d70339674deaece0d7641e.tar.xz | |
Implement initial VK_EXT_debug_utils changes
This affects the loader, scripts, and layers and introduces the
changes to support the VK_EXT_debug_utils extension.
Change-Id: Ia5336f63e85b00f1e59416c06aacd4ae331fd692
Diffstat (limited to 'layers')
| -rw-r--r-- | layers/core_validation.cpp | 138 | ||||
| -rw-r--r-- | layers/object_tracker.h | 20 | ||||
| -rw-r--r-- | layers/object_tracker_utils.cpp | 210 | ||||
| -rw-r--r-- | layers/parameter_validation.h | 11 | ||||
| -rw-r--r-- | layers/parameter_validation_utils.cpp | 137 | ||||
| -rw-r--r-- | layers/threading.cpp | 126 | ||||
| -rw-r--r-- | layers/threading.h | 27 | ||||
| -rw-r--r-- | layers/unique_objects.cpp | 89 | ||||
| -rw-r--r-- | layers/unique_objects.h | 13 | ||||
| -rw-r--r-- | layers/vk_layer_config.cpp | 55 | ||||
| -rw-r--r-- | layers/vk_layer_config.h | 4 | ||||
| -rw-r--r-- | layers/vk_layer_logging.h | 845 | ||||
| -rw-r--r-- | layers/vk_layer_utils.cpp | 72 | ||||
| -rw-r--r-- | layers/vk_layer_utils.h | 13 |
14 files changed, 1507 insertions, 253 deletions
diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 1f1ec3b5..51223dca 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -144,7 +144,8 @@ static const VkDeviceMemory MEMORY_UNBOUND = VkDeviceMemory(~((uint64_t)(0)) - 1 struct instance_layer_data { VkInstance instance = VK_NULL_HANDLE; debug_report_data *report_data = nullptr; - std::vector<VkDebugReportCallbackEXT> logging_callback; + vector<VkDebugReportCallbackEXT> logging_callback; + vector<VkDebugUtilsMessengerEXT> logging_messenger; VkLayerInstanceDispatchTable dispatch_table; CALL_STATE vkEnumeratePhysicalDevicesState = UNCALLED; @@ -2032,7 +2033,9 @@ bool outsideRenderPass(const layer_data *dev_data, GLOBAL_CB_NODE *pCB, const ch } static void init_core_validation(instance_layer_data *instance_data, const VkAllocationCallbacks *pAllocator) { - layer_debug_actions(instance_data->report_data, instance_data->logging_callback, pAllocator, "lunarg_core_validation"); + layer_debug_report_actions(instance_data->report_data, instance_data->logging_callback, pAllocator, "lunarg_core_validation"); + layer_debug_messenger_actions(instance_data->report_data, instance_data->logging_messenger, pAllocator, + "lunarg_core_validation"); } // For the given ValidationCheck enum, set all relevant instance disabled flags to true @@ -2070,7 +2073,7 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreat instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(*pInstance), instance_layer_data_map); instance_data->instance = *pInstance; layer_init_instance_dispatch_table(*pInstance, &instance_data->dispatch_table, fpGetInstanceProcAddr); - instance_data->report_data = debug_report_create_instance( + instance_data->report_data = debug_utils_create_instance( &instance_data->dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames); instance_data->api_version = instance_data->extensions.InitFromInstanceCreateInfo( @@ -2098,13 +2101,18 @@ VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocati lock_guard_t lock(global_lock); // Clean up logging callback, if any + while (instance_data->logging_messenger.size() > 0) { + VkDebugUtilsMessengerEXT messenger = instance_data->logging_messenger.back(); + layer_destroy_messenger_callback(instance_data->report_data, messenger, pAllocator); + instance_data->logging_messenger.pop_back(); + } while (instance_data->logging_callback.size() > 0) { VkDebugReportCallbackEXT callback = instance_data->logging_callback.back(); - layer_destroy_msg_callback(instance_data->report_data, callback, pAllocator); + layer_destroy_report_callback(instance_data->report_data, callback, pAllocator); instance_data->logging_callback.pop_back(); } - layer_debug_report_destroy_instance(instance_data->report_data); + layer_debug_utils_destroy_instance(instance_data->report_data); FreeLayerDataPtr(key, instance_layer_data_map); } @@ -2277,7 +2285,7 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDevice // Save PhysicalDevice handle device_data->physical_device = gpu; - device_data->report_data = layer_debug_report_create_device(instance_data->report_data, *pDevice); + device_data->report_data = layer_debug_utils_create_device(instance_data->report_data, *pDevice); // Get physical device limits for this device instance_data->dispatch_table.GetPhysicalDeviceProperties(gpu, &(device_data->phys_dev_properties.properties)); @@ -2342,7 +2350,7 @@ VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCall // Queues persist until device is destroyed dev_data->queueMap.clear(); // Report any memory leaks - layer_debug_report_destroy_device(device); + layer_debug_utils_destroy_device(device); lock.unlock(); #if DISPATCH_MAP_DEBUG @@ -11713,6 +11721,107 @@ VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDev return result; } +// VK_EXT_debug_utils commands +VKAPI_ATTR VkResult VKAPI_CALL SetDebugUtilsObjectNameEXT(VkDevice device, const VkDebugUtilsObjectNameInfoEXT *pNameInfo) { + layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); + VkResult result = VK_SUCCESS; + if (pNameInfo->pObjectName) { + dev_data->report_data->debugUtilsObjectNameMap->insert( + std::make_pair<uint64_t, std::string>((uint64_t &&) pNameInfo->objectHandle, pNameInfo->pObjectName)); + } else { + dev_data->report_data->debugUtilsObjectNameMap->erase(pNameInfo->objectHandle); + } + if (nullptr != dev_data->dispatch_table.SetDebugUtilsObjectNameEXT) { + result = dev_data->dispatch_table.SetDebugUtilsObjectNameEXT(device, pNameInfo); + } + return result; +} + +VKAPI_ATTR VkResult VKAPI_CALL SetDebugUtilsObjectTagEXT(VkDevice device, const VkDebugUtilsObjectTagInfoEXT *pTagInfo) { + layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); + VkResult result = VK_SUCCESS; + if (nullptr != dev_data->dispatch_table.SetDebugUtilsObjectTagEXT) { + result = dev_data->dispatch_table.SetDebugUtilsObjectTagEXT(device, pTagInfo); + } + return result; +} + +VKAPI_ATTR void VKAPI_CALL QueueBeginDebugUtilsLabelEXT(VkQueue queue, const VkDebugUtilsLabelEXT *pLabelInfo) { + layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map); + BeginQueueDebugUtilsLabel(dev_data->report_data, queue, pLabelInfo); + if (nullptr != dev_data->dispatch_table.QueueBeginDebugUtilsLabelEXT) { + dev_data->dispatch_table.QueueBeginDebugUtilsLabelEXT(queue, pLabelInfo); + } +} + +VKAPI_ATTR void VKAPI_CALL QueueEndDebugUtilsLabelEXT(VkQueue queue) { + layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map); + if (nullptr != dev_data->dispatch_table.QueueEndDebugUtilsLabelEXT) { + dev_data->dispatch_table.QueueEndDebugUtilsLabelEXT(queue); + } + EndQueueDebugUtilsLabel(dev_data->report_data, queue); +} + +VKAPI_ATTR void VKAPI_CALL QueueInsertDebugUtilsLabelEXT(VkQueue queue, const VkDebugUtilsLabelEXT *pLabelInfo) { + layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map); + InsertQueueDebugUtilsLabel(dev_data->report_data, queue, pLabelInfo); + if (nullptr != dev_data->dispatch_table.QueueInsertDebugUtilsLabelEXT) { + dev_data->dispatch_table.QueueInsertDebugUtilsLabelEXT(queue, pLabelInfo); + } +} + +VKAPI_ATTR void VKAPI_CALL CmdBeginDebugUtilsLabelEXT(VkCommandBuffer commandBuffer, const VkDebugUtilsLabelEXT *pLabelInfo) { + layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); + BeginCmdDebugUtilsLabel(dev_data->report_data, commandBuffer, pLabelInfo); + if (nullptr != dev_data->dispatch_table.CmdBeginDebugUtilsLabelEXT) { + dev_data->dispatch_table.CmdBeginDebugUtilsLabelEXT(commandBuffer, pLabelInfo); + } +} + +VKAPI_ATTR void VKAPI_CALL CmdEndDebugUtilsLabelEXT(VkCommandBuffer commandBuffer) { + layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); + if (nullptr != dev_data->dispatch_table.CmdEndDebugUtilsLabelEXT) { + dev_data->dispatch_table.CmdEndDebugUtilsLabelEXT(commandBuffer); + } + EndCmdDebugUtilsLabel(dev_data->report_data, commandBuffer); +} + +VKAPI_ATTR void VKAPI_CALL CmdInsertDebugUtilsLabelEXT(VkCommandBuffer commandBuffer, const VkDebugUtilsLabelEXT *pLabelInfo) { + layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); + InsertCmdDebugUtilsLabel(dev_data->report_data, commandBuffer, pLabelInfo); + if (nullptr != dev_data->dispatch_table.CmdInsertDebugUtilsLabelEXT) { + dev_data->dispatch_table.CmdInsertDebugUtilsLabelEXT(commandBuffer, pLabelInfo); + } +} + +VKAPI_ATTR VkResult VKAPI_CALL CreateDebugUtilsMessengerEXT(VkInstance instance, + const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo, + const VkAllocationCallbacks *pAllocator, + VkDebugUtilsMessengerEXT *pMessenger) { + instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); + VkResult result = instance_data->dispatch_table.CreateDebugUtilsMessengerEXT(instance, pCreateInfo, pAllocator, pMessenger); + + if (VK_SUCCESS == result) { + result = layer_create_messenger_callback(instance_data->report_data, false, pCreateInfo, pAllocator, pMessenger); + } + return result; +} + +VKAPI_ATTR void VKAPI_CALL DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger, + const VkAllocationCallbacks *pAllocator) { + instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); + instance_data->dispatch_table.DestroyDebugUtilsMessengerEXT(instance, messenger, pAllocator); + layer_destroy_messenger_callback(instance_data->report_data, messenger, pAllocator); +} + +VKAPI_ATTR void VKAPI_CALL SubmitDebugUtilsMessageEXT(VkInstance instance, VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageTypes, + const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData) { + instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); + instance_data->dispatch_table.SubmitDebugUtilsMessageEXT(instance, messageSeverity, messageTypes, pCallbackData); +} + +// VK_EXT_debug_report commands VKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo, const VkAllocationCallbacks *pAllocator, @@ -11721,7 +11830,7 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(VkInstance instance, VkResult res = instance_data->dispatch_table.CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback); if (VK_SUCCESS == res) { lock_guard_t lock(global_lock); - res = layer_create_msg_callback(instance_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback); + res = layer_create_report_callback(instance_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback); } return res; } @@ -11731,7 +11840,7 @@ VKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance, Vk instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); instance_data->dispatch_table.DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator); lock_guard_t lock(global_lock); - layer_destroy_msg_callback(instance_data->report_data, msgCallback, pAllocator); + layer_destroy_report_callback(instance_data->report_data, msgCallback, pAllocator); } VKAPI_ATTR void VKAPI_CALL DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, @@ -12388,6 +12497,17 @@ static const std::unordered_map<std::string, void *> name_to_funcptr_map = { {"vkMergeValidationCachesEXT", (void *)MergeValidationCachesEXT}, {"vkCmdSetDiscardRectangleEXT", (void *)CmdSetDiscardRectangleEXT}, {"vkCmdSetSampleLocationsEXT", (void *)CmdSetSampleLocationsEXT}, + {"vkSetDebugUtilsObjectNameEXT", (void *)SetDebugUtilsObjectNameEXT}, + {"vkSetDebugUtilsObjectTagEXT", (void *)SetDebugUtilsObjectTagEXT}, + {"vkQueueBeginDebugUtilsLabelEXT", (void *)QueueBeginDebugUtilsLabelEXT}, + {"vkQueueEndDebugUtilsLabelEXT", (void *)QueueEndDebugUtilsLabelEXT}, + {"vkQueueInsertDebugUtilsLabelEXT", (void *)QueueInsertDebugUtilsLabelEXT}, + {"vkCmdBeginDebugUtilsLabelEXT", (void *)CmdBeginDebugUtilsLabelEXT}, + {"vkCmdEndDebugUtilsLabelEXT", (void *)CmdEndDebugUtilsLabelEXT}, + {"vkCmdInsertDebugUtilsLabelEXT", (void *)CmdInsertDebugUtilsLabelEXT}, + {"vkCreateDebugUtilsMessengerEXT", (void *)CreateDebugUtilsMessengerEXT}, + {"vkDestroyDebugUtilsMessengerEXT", (void *)DestroyDebugUtilsMessengerEXT}, + {"vkSubmitDebugUtilsMessageEXT", (void *)SubmitDebugUtilsMessageEXT}, }; VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) { diff --git a/layers/object_tracker.h b/layers/object_tracker.h index d9fdf8b4..5a6f545d 100644 --- a/layers/object_tracker.h +++ b/layers/object_tracker.h @@ -35,7 +35,6 @@ #include "vk_layer_table.h" #include "vk_object_types.h" #include "vulkan/vk_layer.h" -#include "vk_object_types.h" #include "vk_enum_string_helper.h" #include "vk_layer_extension_utils.h" #include "vk_layer_table.h" @@ -96,11 +95,15 @@ struct layer_data { debug_report_data *report_data; std::vector<VkDebugReportCallbackEXT> logging_callback; + std::vector<VkDebugUtilsMessengerEXT> logging_messenger; // The following are for keeping track of the temporary callbacks that can // be used in vkCreateInstance and vkDestroyInstance: - uint32_t num_tmp_callbacks; - VkDebugReportCallbackCreateInfoEXT *tmp_dbg_create_infos; - VkDebugReportCallbackEXT *tmp_callbacks; + uint32_t num_tmp_report_callbacks; + VkDebugReportCallbackCreateInfoEXT *tmp_report_create_infos; + VkDebugReportCallbackEXT *tmp_report_callbacks; + uint32_t num_tmp_debug_messengers; + VkDebugUtilsMessengerCreateInfoEXT *tmp_messenger_create_infos; + VkDebugUtilsMessengerEXT *tmp_debug_messengers; std::vector<VkQueueFamilyProperties> queue_family_properties; @@ -119,9 +122,12 @@ struct layer_data { num_objects{}, num_total_objects(0), report_data(nullptr), - num_tmp_callbacks(0), - tmp_dbg_create_infos(nullptr), - tmp_callbacks(nullptr), + num_tmp_report_callbacks(0), + tmp_report_create_infos(nullptr), + tmp_report_callbacks(nullptr), + num_tmp_debug_messengers(0), + tmp_messenger_create_infos(nullptr), + tmp_debug_messengers(nullptr), object_map{}, dispatch_table{} { object_map.resize(kVulkanObjectTypeMax + 1); diff --git a/layers/object_tracker_utils.cpp b/layers/object_tracker_utils.cpp index c9573dd3..177c1455 100644 --- a/layers/object_tracker_utils.cpp +++ b/layers/object_tracker_utils.cpp @@ -32,7 +32,8 @@ uint64_t object_track_index = 0; uint32_t loader_layer_if_version = CURRENT_LOADER_LAYER_INTERFACE_VERSION; void InitObjectTracker(layer_data *my_data, const VkAllocationCallbacks *pAllocator) { - layer_debug_actions(my_data->report_data, my_data->logging_callback, pAllocator, "lunarg_object_tracker"); + layer_debug_report_actions(my_data->report_data, my_data->logging_callback, pAllocator, "lunarg_object_tracker"); + layer_debug_messenger_actions(my_data->report_data, my_data->logging_messenger, pAllocator, "lunarg_object_tracker"); } // Add new queue to head of global queue list @@ -328,12 +329,13 @@ VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocati layer_data *instance_data = GetLayerDataPtr(key, layer_data_map); // Enable the temporary callback(s) here to catch cleanup issues: - bool callback_setup = false; - if (instance_data->num_tmp_callbacks > 0) { - if (!layer_enable_tmp_callbacks(instance_data->report_data, instance_data->num_tmp_callbacks, - instance_data->tmp_dbg_create_infos, instance_data->tmp_callbacks)) { - callback_setup = true; - } + if (instance_data->num_tmp_debug_messengers > 0) { + layer_enable_tmp_debug_messengers(instance_data->report_data, instance_data->num_tmp_debug_messengers, + instance_data->tmp_messenger_create_infos, instance_data->tmp_debug_messengers); + } + if (instance_data->num_tmp_report_callbacks > 0) { + layer_enable_tmp_report_callbacks(instance_data->report_data, instance_data->num_tmp_report_callbacks, + instance_data->tmp_report_create_infos, instance_data->tmp_report_callbacks); } // TODO: The instance handle can not be validated here. The loader will likely have to validate it. @@ -375,22 +377,32 @@ VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocati pInstanceTable->DestroyInstance(instance, pAllocator); // Disable and cleanup the temporary callback(s): - if (callback_setup) { - layer_disable_tmp_callbacks(instance_data->report_data, instance_data->num_tmp_callbacks, instance_data->tmp_callbacks); + layer_disable_tmp_debug_messengers(instance_data->report_data, instance_data->num_tmp_debug_messengers, + instance_data->tmp_debug_messengers); + layer_disable_tmp_report_callbacks(instance_data->report_data, instance_data->num_tmp_report_callbacks, + instance_data->tmp_report_callbacks); + if (instance_data->num_tmp_debug_messengers > 0) { + layer_free_tmp_debug_messengers(instance_data->tmp_messenger_create_infos, instance_data->tmp_debug_messengers); + instance_data->num_tmp_debug_messengers = 0; } - if (instance_data->num_tmp_callbacks > 0) { - layer_free_tmp_callbacks(instance_data->tmp_dbg_create_infos, instance_data->tmp_callbacks); - instance_data->num_tmp_callbacks = 0; + if (instance_data->num_tmp_report_callbacks > 0) { + layer_free_tmp_report_callbacks(instance_data->tmp_report_create_infos, instance_data->tmp_report_callbacks); + instance_data->num_tmp_report_callbacks = 0; } // Clean up logging callback, if any + while (instance_data->logging_messenger.size() > 0) { + VkDebugUtilsMessengerEXT messenger = instance_data->logging_messenger.back(); + layer_destroy_messenger_callback(instance_data->report_data, messenger, pAllocator); + instance_data->logging_messenger.pop_back(); + } while (instance_data->logging_callback.size() > 0) { VkDebugReportCallbackEXT callback = instance_data->logging_callback.back(); - layer_destroy_msg_callback(instance_data->report_data, callback, pAllocator); + layer_destroy_report_callback(instance_data->report_data, callback, pAllocator); instance_data->logging_callback.pop_back(); } - layer_debug_report_destroy_instance(instance_data->report_data); + layer_debug_utils_destroy_instance(instance_data->report_data); FreeLayerDataPtr(key, layer_data_map); lock.unlock(); @@ -572,7 +584,7 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(VkInstance instance, VkResult result = pInstanceTable->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback); if (VK_SUCCESS == result) { layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map); - result = layer_create_msg_callback(instance_data->report_data, false, pCreateInfo, pAllocator, pCallback); + result = layer_create_report_callback(instance_data->report_data, false, pCreateInfo, pAllocator, pCallback); CreateObject(instance, *pCallback, kVulkanObjectTypeDebugReportCallbackEXT, pAllocator); } return result; @@ -583,7 +595,7 @@ VKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance, Vk VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(ot_instance_table_map, instance); pInstanceTable->DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator); layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map); - layer_destroy_msg_callback(instance_data->report_data, msgCallback, pAllocator); + layer_destroy_report_callback(instance_data->report_data, msgCallback, pAllocator); DestroyObject(instance, msgCallback, kVulkanObjectTypeDebugReportCallbackEXT, pAllocator, VALIDATION_ERROR_242009b4, VALIDATION_ERROR_242009b6); } @@ -595,7 +607,159 @@ VKAPI_ATTR void VKAPI_CALL DebugReportMessageEXT(VkInstance instance, VkDebugRep pInstanceTable->DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg); } -static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}}; +// VK_EXT_debug_utils commands +VKAPI_ATTR VkResult VKAPI_CALL SetDebugUtilsObjectNameEXT(VkDevice device, const VkDebugUtilsObjectNameInfoEXT *pNameInfo) { + bool skip = VK_FALSE; + std::unique_lock<std::mutex> lock(global_lock); + skip |= ValidateObject(device, device, kVulkanObjectTypeDevice, false, VALIDATION_ERROR_UNDEFINED, VALIDATION_ERROR_UNDEFINED); + lock.unlock(); + if (skip) { + return VK_ERROR_VALIDATION_FAILED_EXT; + } + layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); + if (pNameInfo->pObjectName) { + dev_data->report_data->debugUtilsObjectNameMap->insert( + std::make_pair<uint64_t, std::string>((uint64_t &&) pNameInfo->objectHandle, pNameInfo->pObjectName)); + } else { + dev_data->report_data->debugUtilsObjectNameMap->erase(pNameInfo->objectHandle); + } + VkResult result = dev_data->dispatch_table.SetDebugUtilsObjectNameEXT(device, pNameInfo); + return result; +} + +VKAPI_ATTR VkResult VKAPI_CALL SetDebugUtilsObjectTagEXT(VkDevice device, const VkDebugUtilsObjectTagInfoEXT *pTagInfo) { + bool skip = VK_FALSE; + std::unique_lock<std::mutex> lock(global_lock); + skip |= ValidateObject(device, device, kVulkanObjectTypeDevice, false, VALIDATION_ERROR_UNDEFINED, VALIDATION_ERROR_UNDEFINED); + lock.unlock(); + if (skip) { + return VK_ERROR_VALIDATION_FAILED_EXT; + } + layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); + VkResult result = dev_data->dispatch_table.SetDebugUtilsObjectTagEXT(device, pTagInfo); + return result; +} + +VKAPI_ATTR void VKAPI_CALL QueueBeginDebugUtilsLabelEXT(VkQueue queue, const VkDebugUtilsLabelEXT *pLabelInfo) { + bool skip = VK_FALSE; + std::unique_lock<std::mutex> lock(global_lock); + skip |= ValidateObject(queue, queue, kVulkanObjectTypeQueue, false, VALIDATION_ERROR_UNDEFINED, VALIDATION_ERROR_UNDEFINED); + lock.unlock(); + layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map); + if (!skip) { + BeginQueueDebugUtilsLabel(dev_data->report_data, queue, pLabelInfo); + if (dev_data->dispatch_table.QueueBeginDebugUtilsLabelEXT) { + dev_data->dispatch_table.QueueBeginDebugUtilsLabelEXT(queue, pLabelInfo); + } + } +} + +VKAPI_ATTR void VKAPI_CALL QueueEndDebugUtilsLabelEXT(VkQueue queue) { + bool skip = VK_FALSE; + std::unique_lock<std::mutex> lock(global_lock); + skip |= ValidateObject(queue, queue, kVulkanObjectTypeQueue, false, VALIDATION_ERROR_UNDEFINED, VALIDATION_ERROR_UNDEFINED); + lock.unlock(); + layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map); + if (!skip) { + if (dev_data->dispatch_table.QueueEndDebugUtilsLabelEXT) { + dev_data->dispatch_table.QueueEndDebugUtilsLabelEXT(queue); + } + EndQueueDebugUtilsLabel(dev_data->report_data, queue); + } +} + +VKAPI_ATTR void VKAPI_CALL QueueInsertDebugUtilsLabelEXT(VkQueue queue, const VkDebugUtilsLabelEXT *pLabelInfo) { + bool skip = VK_FALSE; + std::unique_lock<std::mutex> lock(global_lock); + skip |= ValidateObject(queue, queue, kVulkanObjectTypeQueue, false, VALIDATION_ERROR_UNDEFINED, VALIDATION_ERROR_UNDEFINED); + lock.unlock(); + layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map); + if (!skip) { + InsertQueueDebugUtilsLabel(dev_data->report_data, queue, pLabelInfo); + if (dev_data->dispatch_table.QueueInsertDebugUtilsLabelEXT) { + dev_data->dispatch_table.QueueInsertDebugUtilsLabelEXT(queue, pLabelInfo); + } + } +} + +VKAPI_ATTR void VKAPI_CALL CmdBeginDebugUtilsLabelEXT(VkCommandBuffer commandBuffer, const VkDebugUtilsLabelEXT *pLabelInfo) { + bool skip = VK_FALSE; + std::unique_lock<std::mutex> lock(global_lock); + skip |= ValidateObject(commandBuffer, commandBuffer, kVulkanObjectTypeCommandBuffer, false, VALIDATION_ERROR_UNDEFINED, + VALIDATION_ERROR_UNDEFINED); + lock.unlock(); + layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); + if (!skip) { + BeginCmdDebugUtilsLabel(dev_data->report_data, commandBuffer, pLabelInfo); + if (dev_data->dispatch_table.CmdBeginDebugUtilsLabelEXT) { + dev_data->dispatch_table.CmdBeginDebugUtilsLabelEXT(commandBuffer, pLabelInfo); + } + } +} + +VKAPI_ATTR void VKAPI_CALL CmdEndDebugUtilsLabelEXT(VkCommandBuffer commandBuffer) { + bool skip = VK_FALSE; + std::unique_lock<std::mutex> lock(global_lock); + skip |= ValidateObject(commandBuffer, commandBuffer, kVulkanObjectTypeCommandBuffer, false, VALIDATION_ERROR_UNDEFINED, + VALIDATION_ERROR_UNDEFINED); + lock.unlock(); + layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); + if (!skip) { + if (dev_data->dispatch_table.CmdEndDebugUtilsLabelEXT) { + dev_data->dispatch_table.CmdEndDebugUtilsLabelEXT(commandBuffer); + } + EndCmdDebugUtilsLabel(dev_data->report_data, commandBuffer); + } +} + +VKAPI_ATTR void VKAPI_CALL CmdInsertDebugUtilsLabelEXT(VkCommandBuffer commandBuffer, const VkDebugUtilsLabelEXT *pLabelInfo) { + bool skip = VK_FALSE; + std::unique_lock<std::mutex> lock(global_lock); + skip |= ValidateObject(commandBuffer, commandBuffer, kVulkanObjectTypeCommandBuffer, false, VALIDATION_ERROR_UNDEFINED, + VALIDATION_ERROR_UNDEFINED); + lock.unlock(); + layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); + if (!skip) { + InsertCmdDebugUtilsLabel(dev_data->report_data, commandBuffer, pLabelInfo); + if (dev_data->dispatch_table.CmdInsertDebugUtilsLabelEXT) { + dev_data->dispatch_table.CmdInsertDebugUtilsLabelEXT(commandBuffer, pLabelInfo); + } + } +} + +VKAPI_ATTR VkResult VKAPI_CALL CreateDebugUtilsMessengerEXT(VkInstance instance, + const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo, + const VkAllocationCallbacks *pAllocator, + VkDebugUtilsMessengerEXT *pMessenger) { + VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(ot_instance_table_map, instance); + VkResult result = pInstanceTable->CreateDebugUtilsMessengerEXT(instance, pCreateInfo, pAllocator, pMessenger); + if (VK_SUCCESS == result) { + layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map); + result = layer_create_messenger_callback(instance_data->report_data, false, pCreateInfo, pAllocator, pMessenger); + CreateObject(instance, *pMessenger, kVulkanObjectTypeDebugUtilsMessengerEXT, pAllocator); + } + return result; +} + +VKAPI_ATTR void VKAPI_CALL DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger, + const VkAllocationCallbacks *pAllocator) { + VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(ot_instance_table_map, instance); + pInstanceTable->DestroyDebugUtilsMessengerEXT(instance, messenger, pAllocator); + layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map); + layer_destroy_messenger_callback(instance_data->report_data, messenger, pAllocator); + DestroyObject(instance, messenger, kVulkanObjectTypeDebugUtilsMessengerEXT, pAllocator, VALIDATION_ERROR_UNDEFINED, + VALIDATION_ERROR_UNDEFINED); +} + +VKAPI_ATTR void VKAPI_CALL SubmitDebugUtilsMessageEXT(VkInstance instance, VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageTypes, + const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData) { + VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(ot_instance_table_map, instance); + pInstanceTable->SubmitDebugUtilsMessageEXT(instance, messageSeverity, messageTypes, pCallbackData); +} + +static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}, + {VK_EXT_DEBUG_UTILS_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_SPEC_VERSION}}; static const VkLayerProperties globalLayerProps = {"VK_LAYER_LUNARG_object_tracker", VK_LAYER_API_VERSION, // specVersion @@ -656,7 +820,7 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice physicalDevice, con } layer_data *device_data = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map); - device_data->report_data = layer_debug_report_create_device(phy_dev_data->report_data, *pDevice); + device_data->report_data = layer_debug_utils_create_device(phy_dev_data->report_data, *pDevice); layer_init_device_dispatch_table(*pDevice, &device_data->dispatch_table, fpGetDeviceProcAddr); // Add link back to physDev @@ -779,11 +943,13 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreat // Look for one or more debug report create info structures, and copy the // callback(s) for each one found (for use by vkDestroyInstance) - layer_copy_tmp_callbacks(pCreateInfo->pNext, &instance_data->num_tmp_callbacks, &instance_data->tmp_dbg_create_infos, - &instance_data->tmp_callbacks); + layer_copy_tmp_debug_messengers(pCreateInfo->pNext, &instance_data->num_tmp_debug_messengers, + &instance_data->tmp_messenger_create_infos, &instance_data->tmp_debug_messengers); + layer_copy_tmp_report_callbacks(pCreateInfo->pNext, &instance_data->num_tmp_report_callbacks, + &instance_data->tmp_report_create_infos, &instance_data->tmp_report_callbacks); - instance_data->report_data = debug_report_create_instance(pInstanceTable, *pInstance, pCreateInfo->enabledExtensionCount, - pCreateInfo->ppEnabledExtensionNames); + instance_data->report_data = debug_utils_create_instance(pInstanceTable, *pInstance, pCreateInfo->enabledExtensionCount, + pCreateInfo->ppEnabledExtensionNames); InitObjectTracker(instance_data, pAllocator); diff --git a/layers/parameter_validation.h b/layers/parameter_validation.h index 49ff279a..d03152c1 100644 --- a/layers/parameter_validation.h +++ b/layers/parameter_validation.h @@ -61,12 +61,17 @@ struct instance_layer_data { debug_report_data *report_data = nullptr; std::vector<VkDebugReportCallbackEXT> logging_callback; + std::vector<VkDebugUtilsMessengerEXT> logging_messenger; // The following are for keeping track of the temporary callbacks that can // be used in vkCreateInstance and vkDestroyInstance: - uint32_t num_tmp_callbacks = 0; - VkDebugReportCallbackCreateInfoEXT *tmp_dbg_create_infos = nullptr; - VkDebugReportCallbackEXT *tmp_callbacks = nullptr; + uint32_t num_tmp_report_callbacks = 0; + VkDebugReportCallbackCreateInfoEXT *tmp_report_create_infos = nullptr; + VkDebugReportCallbackEXT *tmp_report_callbacks = nullptr; + uint32_t num_tmp_debug_messengers = 0; + VkDebugUtilsMessengerCreateInfoEXT *tmp_messenger_create_infos = nullptr; + VkDebugUtilsMessengerEXT *tmp_debug_messengers = nullptr; + InstanceExtensions extensions = {}; VkLayerInstanceDispatchTable dispatch_table = {}; uint32_t api_version; diff --git a/layers/parameter_validation_utils.cpp b/layers/parameter_validation_utils.cpp index b818159c..3dfd27ce 100644 --- a/layers/parameter_validation_utils.cpp +++ b/layers/parameter_validation_utils.cpp @@ -79,6 +79,12 @@ extern bool parameter_validation_vkCreateDebugReportCallbackEXT(VkInstance insta VkDebugReportCallbackEXT *pMsgCallback); extern bool parameter_validation_vkDestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT msgCallback, const VkAllocationCallbacks *pAllocator); +extern bool parameter_validation_vkCreateDebugUtilsMessengerEXT(VkInstance instance, + const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo, + const VkAllocationCallbacks *pAllocator, + VkDebugUtilsMessengerEXT *pMessenger); +extern bool parameter_validation_vkDestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger, + const VkAllocationCallbacks *pAllocator); extern bool parameter_validation_vkCreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkCommandPool *pCommandPool); extern bool parameter_validation_vkCreateRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo, @@ -96,10 +102,14 @@ std::unordered_map<void *, instance_layer_data *> instance_layer_data_map; void InitializeManualParameterValidationFunctionPointers(void); static void init_parameter_validation(instance_layer_data *instance_data, const VkAllocationCallbacks *pAllocator) { - layer_debug_actions(instance_data->report_data, instance_data->logging_callback, pAllocator, "lunarg_parameter_validation"); + layer_debug_report_actions(instance_data->report_data, instance_data->logging_callback, pAllocator, + "lunarg_parameter_validation"); + layer_debug_messenger_actions(instance_data->report_data, instance_data->logging_messenger, pAllocator, + "lunarg_parameter_validation"); } -static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}}; +static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}, + {VK_EXT_DEBUG_UTILS_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_SPEC_VERSION}}; static const VkLayerProperties global_layer = { "VK_LAYER_LUNARG_parameter_validation", @@ -216,21 +226,39 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCreateInfo *pCre layer_init_instance_dispatch_table(*pInstance, &my_instance_data->dispatch_table, fpGetInstanceProcAddr); my_instance_data->instance = *pInstance; my_instance_data->report_data = - debug_report_create_instance(&my_instance_data->dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount, - pCreateInfo->ppEnabledExtensionNames); + debug_utils_create_instance(&my_instance_data->dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount, + pCreateInfo->ppEnabledExtensionNames); // Look for one or more debug report create info structures // and setup a callback(s) for each one found. - if (!layer_copy_tmp_callbacks(pCreateInfo->pNext, &my_instance_data->num_tmp_callbacks, - &my_instance_data->tmp_dbg_create_infos, &my_instance_data->tmp_callbacks)) { - if (my_instance_data->num_tmp_callbacks > 0) { + if (!layer_copy_tmp_debug_messengers(pCreateInfo->pNext, &my_instance_data->num_tmp_debug_messengers, + &my_instance_data->tmp_messenger_create_infos, + &my_instance_data->tmp_debug_messengers)) { + if (my_instance_data->num_tmp_debug_messengers > 0) { + // Setup the temporary callback(s) here to catch early issues: + if (layer_enable_tmp_debug_messengers(my_instance_data->report_data, my_instance_data->num_tmp_debug_messengers, + my_instance_data->tmp_messenger_create_infos, + my_instance_data->tmp_debug_messengers)) { + // Failure of setting up one or more of the callback. + // Therefore, clean up and don't use those callbacks: + layer_free_tmp_debug_messengers(my_instance_data->tmp_messenger_create_infos, + my_instance_data->tmp_debug_messengers); + my_instance_data->num_tmp_debug_messengers = 0; + } + } + } + if (!layer_copy_tmp_report_callbacks(pCreateInfo->pNext, &my_instance_data->num_tmp_report_callbacks, + &my_instance_data->tmp_report_create_infos, &my_instance_data->tmp_report_callbacks)) { + if (my_instance_data->num_tmp_report_callbacks > 0) { // Setup the temporary callback(s) here to catch early issues: - if (layer_enable_tmp_callbacks(my_instance_data->report_data, my_instance_data->num_tmp_callbacks, - my_instance_data->tmp_dbg_create_infos, my_instance_data->tmp_callbacks)) { + if (layer_enable_tmp_report_callbacks(my_instance_data->report_data, my_instance_data->num_tmp_report_callbacks, + my_instance_data->tmp_report_create_infos, + my_instance_data->tmp_report_callbacks)) { // Failure of setting up one or more of the callback. // Therefore, clean up and don't use those callbacks: - layer_free_tmp_callbacks(my_instance_data->tmp_dbg_create_infos, my_instance_data->tmp_callbacks); - my_instance_data->num_tmp_callbacks = 0; + layer_free_tmp_report_callbacks(my_instance_data->tmp_report_create_infos, + my_instance_data->tmp_report_callbacks); + my_instance_data->num_tmp_report_callbacks = 0; } } } @@ -269,9 +297,13 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCreateInfo *pCre } // Disable the tmp callbacks: - if (my_instance_data->num_tmp_callbacks > 0) { - layer_disable_tmp_callbacks(my_instance_data->report_data, my_instance_data->num_tmp_callbacks, - my_instance_data->tmp_callbacks); + if (my_instance_data->num_tmp_debug_messengers > 0) { + layer_disable_tmp_debug_messengers(my_instance_data->report_data, my_instance_data->num_tmp_debug_messengers, + my_instance_data->tmp_debug_messengers); + } + if (my_instance_data->num_tmp_report_callbacks > 0) { + layer_disable_tmp_report_callbacks(my_instance_data->report_data, my_instance_data->num_tmp_report_callbacks, + my_instance_data->tmp_report_callbacks); } } @@ -286,9 +318,15 @@ VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance, const VkAlloca // Enable the temporary callback(s) here to catch vkDestroyInstance issues: bool callback_setup = false; - if (instance_data->num_tmp_callbacks > 0) { - if (!layer_enable_tmp_callbacks(instance_data->report_data, instance_data->num_tmp_callbacks, - instance_data->tmp_dbg_create_infos, instance_data->tmp_callbacks)) { + if (instance_data->num_tmp_debug_messengers > 0) { + if (!layer_enable_tmp_debug_messengers(instance_data->report_data, instance_data->num_tmp_debug_messengers, + instance_data->tmp_messenger_create_infos, instance_data->tmp_debug_messengers)) { + callback_setup = true; + } + } + if (instance_data->num_tmp_report_callbacks > 0) { + if (!layer_enable_tmp_report_callbacks(instance_data->report_data, instance_data->num_tmp_report_callbacks, + instance_data->tmp_report_create_infos, instance_data->tmp_report_callbacks)) { callback_setup = true; } } @@ -297,24 +335,36 @@ VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance, const VkAlloca // Disable and cleanup the temporary callback(s): if (callback_setup) { - layer_disable_tmp_callbacks(instance_data->report_data, instance_data->num_tmp_callbacks, instance_data->tmp_callbacks); + layer_disable_tmp_debug_messengers(instance_data->report_data, instance_data->num_tmp_debug_messengers, + instance_data->tmp_debug_messengers); + layer_disable_tmp_report_callbacks(instance_data->report_data, instance_data->num_tmp_report_callbacks, + instance_data->tmp_report_callbacks); } - if (instance_data->num_tmp_callbacks > 0) { - layer_free_tmp_callbacks(instance_data->tmp_dbg_create_infos, instance_data->tmp_callbacks); - instance_data->num_tmp_callbacks = 0; + if (instance_data->num_tmp_debug_messengers > 0) { + layer_free_tmp_debug_messengers(instance_data->tmp_messenger_create_infos, instance_data->tmp_debug_messengers); + instance_data->num_tmp_debug_messengers = 0; + } + if (instance_data->num_tmp_report_callbacks > 0) { + layer_free_tmp_report_callbacks(instance_data->tmp_report_create_infos, instance_data->tmp_report_callbacks); + instance_data->num_tmp_report_callbacks = 0; } if (!skip) { instance_data->dispatch_table.DestroyInstance(instance, pAllocator); // Clean up logging callback, if any + while (instance_data->logging_messenger.size() > 0) { + VkDebugUtilsMessengerEXT messenger = instance_data->logging_messenger.back(); + layer_destroy_messenger_callback(instance_data->report_data, messenger, pAllocator); + instance_data->logging_messenger.pop_back(); + } while (instance_data->logging_callback.size() > 0) { VkDebugReportCallbackEXT callback = instance_data->logging_callback.back(); - layer_destroy_msg_callback(instance_data->report_data, callback, pAllocator); + layer_destroy_report_callback(instance_data->report_data, callback, pAllocator); instance_data->logging_callback.pop_back(); } - layer_debug_report_destroy_instance(instance_data->report_data); + layer_debug_utils_destroy_instance(instance_data->report_data); } FreeLayerDataPtr(key, instance_layer_data_map); @@ -330,7 +380,11 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugReportCallbackEXT(VkInstance instanc auto instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); VkResult result = instance_data->dispatch_table.CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback); if (result == VK_SUCCESS) { - result = layer_create_msg_callback(instance_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback); + result = layer_create_report_callback(instance_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback); + // If something happened during this call, clean up the message callback that was created earlier in the lower levels + if (VK_SUCCESS != result) { + instance_data->dispatch_table.DestroyDebugReportCallbackEXT(instance, *pMsgCallback, pAllocator); + } } return result; } @@ -341,7 +395,36 @@ VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(VkInstance instance, if (!skip) { auto instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); instance_data->dispatch_table.DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator); - layer_destroy_msg_callback(instance_data->report_data, msgCallback, pAllocator); + layer_destroy_report_callback(instance_data->report_data, msgCallback, pAllocator); + } +} + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugUtilsMessengerEXT(VkInstance instance, + const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo, + const VkAllocationCallbacks *pAllocator, + VkDebugUtilsMessengerEXT *pMessenger) { + bool skip = parameter_validation_vkCreateDebugUtilsMessengerEXT(instance, pCreateInfo, pAllocator, pMessenger); + if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; + + auto instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); + VkResult result = instance_data->dispatch_table.CreateDebugUtilsMessengerEXT(instance, pCreateInfo, pAllocator, pMessenger); + if (VK_SUCCESS == result) { + result = layer_create_messenger_callback(instance_data->report_data, false, pCreateInfo, pAllocator, pMessenger); + // If something happened during this call, clean up the message callback that was created earlier in the lower levels + if (VK_SUCCESS != result) { + instance_data->dispatch_table.DestroyDebugUtilsMessengerEXT(instance, *pMessenger, pAllocator); + } + } + return result; +} + +VKAPI_ATTR void VKAPI_CALL vkDestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger, + const VkAllocationCallbacks *pAllocator) { + bool skip = parameter_validation_vkDestroyDebugUtilsMessengerEXT(instance, messenger, pAllocator); + if (!skip) { + auto instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); + instance_data->dispatch_table.DestroyDebugUtilsMessengerEXT(instance, messenger, pAllocator); + layer_destroy_messenger_callback(instance_data->report_data, messenger, pAllocator); } } @@ -472,7 +555,7 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(VkPhysicalDevice physicalDevice, c layer_data *my_device_data = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map); assert(my_device_data != nullptr); - my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice); + my_device_data->report_data = layer_debug_utils_create_device(my_instance_data->report_data, *pDevice); layer_init_device_dispatch_table(*pDevice, &my_device_data->dispatch_table, fpGetDeviceProcAddr); // Query and save physical device limits for this device @@ -533,7 +616,7 @@ VKAPI_ATTR void VKAPI_CALL vkDestroyDevice(VkDevice device, const VkAllocationCa } if (!skip) { - layer_debug_report_destroy_device(device); + layer_debug_utils_destroy_device(device); device_data->dispatch_table.DestroyDevice(device, pAllocator); } FreeLayerDataPtr(key, layer_data_map); diff --git a/layers/threading.cpp b/layers/threading.cpp index d27d75f3..ce5f8e3e 100644 --- a/layers/threading.cpp +++ b/layers/threading.cpp @@ -42,7 +42,8 @@ namespace threading { static uint32_t loader_layer_if_version = CURRENT_LOADER_LAYER_INTERFACE_VERSION; static void initThreading(layer_data *my_data, const VkAllocationCallbacks *pAllocator) { - layer_debug_actions(my_data->report_data, my_data->logging_callback, pAllocator, "google_threading"); + layer_debug_report_actions(my_data->report_data, my_data->logging_callback, pAllocator, "google_threading"); + layer_debug_messenger_actions(my_data->report_data, my_data->logging_messenger, pAllocator, "google_threading"); } VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, @@ -67,14 +68,16 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreat my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable; layer_init_instance_dispatch_table(*pInstance, my_data->instance_dispatch_table, fpGetInstanceProcAddr); - my_data->report_data = debug_report_create_instance(my_data->instance_dispatch_table, *pInstance, - pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames); + my_data->report_data = debug_utils_create_instance(my_data->instance_dispatch_table, *pInstance, + pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames); initThreading(my_data, pAllocator); // Look for one or more debug report create info structures, and copy the // callback(s) for each one found (for use by vkDestroyInstance) - layer_copy_tmp_callbacks(pCreateInfo->pNext, &my_data->num_tmp_callbacks, &my_data->tmp_dbg_create_infos, - &my_data->tmp_callbacks); + layer_copy_tmp_debug_messengers(pCreateInfo->pNext, &my_data->num_tmp_debug_messengers, &my_data->tmp_messenger_create_infos, + &my_data->tmp_debug_messengers); + layer_copy_tmp_report_callbacks(pCreateInfo->pNext, &my_data->num_tmp_report_callbacks, &my_data->tmp_report_create_infos, + &my_data->tmp_report_callbacks); return result; } @@ -85,9 +88,15 @@ VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocati // Enable the temporary callback(s) here to catch cleanup issues: bool callback_setup = false; - if (my_data->num_tmp_callbacks > 0) { - if (!layer_enable_tmp_callbacks(my_data->report_data, my_data->num_tmp_callbacks, my_data->tmp_dbg_create_infos, - my_data->tmp_callbacks)) { + if (my_data->num_tmp_debug_messengers > 0) { + if (!layer_enable_tmp_debug_messengers(my_data->report_data, my_data->num_tmp_debug_messengers, + my_data->tmp_messenger_create_infos, my_data->tmp_debug_messengers)) { + callback_setup = true; + } + } + if (my_data->num_tmp_report_callbacks > 0) { + if (!layer_enable_tmp_report_callbacks(my_data->report_data, my_data->num_tmp_report_callbacks, + my_data->tmp_report_create_infos, my_data->tmp_report_callbacks)) { callback_setup = true; } } @@ -105,21 +114,31 @@ VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocati // Disable and cleanup the temporary callback(s): if (callback_setup) { - layer_disable_tmp_callbacks(my_data->report_data, my_data->num_tmp_callbacks, my_data->tmp_callbacks); + layer_disable_tmp_debug_messengers(my_data->report_data, my_data->num_tmp_debug_messengers, my_data->tmp_debug_messengers); + layer_disable_tmp_report_callbacks(my_data->report_data, my_data->num_tmp_report_callbacks, my_data->tmp_report_callbacks); } - if (my_data->num_tmp_callbacks > 0) { - layer_free_tmp_callbacks(my_data->tmp_dbg_create_infos, my_data->tmp_callbacks); - my_data->num_tmp_callbacks = 0; + if (my_data->num_tmp_debug_messengers > 0) { + layer_free_tmp_debug_messengers(my_data->tmp_messenger_create_infos, my_data->tmp_debug_messengers); + my_data->num_tmp_debug_messengers = 0; + } + if (my_data->num_tmp_report_callbacks > 0) { + layer_free_tmp_report_callbacks(my_data->tmp_report_create_infos, my_data->tmp_report_callbacks); + my_data->num_tmp_report_callbacks = 0; } - // Clean up logging callback, if any + // Clean up logging callbacks, if any + while (my_data->logging_messenger.size() > 0) { + VkDebugUtilsMessengerEXT messenger = my_data->logging_messenger.back(); + layer_destroy_messenger_callback(my_data->report_data, messenger, pAllocator); + my_data->logging_messenger.pop_back(); + } while (my_data->logging_callback.size() > 0) { VkDebugReportCallbackEXT callback = my_data->logging_callback.back(); - layer_destroy_msg_callback(my_data->report_data, callback, pAllocator); + layer_destroy_report_callback(my_data->report_data, callback, pAllocator); my_data->logging_callback.pop_back(); } - layer_debug_report_destroy_instance(my_data->report_data); + layer_debug_utils_destroy_instance(my_data->report_data); delete my_data->instance_dispatch_table; FreeLayerDataPtr(key, layer_data_map); } @@ -151,7 +170,7 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDevice my_device_data->device_dispatch_table = new VkLayerDispatchTable; layer_init_device_dispatch_table(*pDevice, my_device_data->device_dispatch_table, fpGetDeviceProcAddr); - my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice); + my_device_data->report_data = layer_debug_utils_create_device(my_instance_data->report_data, *pDevice); return result; } @@ -194,8 +213,8 @@ VKAPI_ATTR VkResult VKAPI_CALL GetSwapchainImagesKHR(VkDevice device, VkSwapchai return result; } -static const VkExtensionProperties threading_extensions[] = { - {VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}}; +static const VkExtensionProperties threading_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}, + {VK_EXT_DEBUG_UTILS_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_SPEC_VERSION}}; static const VkLayerProperties layerProps = { "VK_LAYER_GOOGLE_threading", @@ -272,6 +291,52 @@ VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance in return pTable->GetPhysicalDeviceProcAddr(instance, funcName); } +// VK_EXT_debug_utils commands +VKAPI_ATTR VkResult VKAPI_CALL CreateDebugUtilsMessengerEXT(VkInstance instance, + const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo, + const VkAllocationCallbacks *pAllocator, + VkDebugUtilsMessengerEXT *pMessenger) { + layer_data *my_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map); + bool threadChecks = startMultiThread(); + if (threadChecks) { + startReadObject(my_data, instance); + } + VkResult result = my_data->instance_dispatch_table->CreateDebugUtilsMessengerEXT(instance, pCreateInfo, pAllocator, pMessenger); + + if (VK_SUCCESS == result) { + result = layer_create_messenger_callback(my_data->report_data, false, pCreateInfo, pAllocator, pMessenger); + // If something happened during this call, clean up the message callback that was created earlier in the lower levels + if (VK_SUCCESS != result) { + my_data->instance_dispatch_table->DestroyDebugUtilsMessengerEXT(instance, *pMessenger, pAllocator); + } + } + if (threadChecks) { + finishReadObject(my_data, instance); + } else { + finishMultiThread(); + } + return result; +} + +VKAPI_ATTR void VKAPI_CALL DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger, + const VkAllocationCallbacks *pAllocator) { + layer_data *my_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map); + bool threadChecks = startMultiThread(); + if (threadChecks) { + startReadObject(my_data, instance); + startWriteObject(my_data, messenger); + } + my_data->instance_dispatch_table->DestroyDebugUtilsMessengerEXT(instance, messenger, pAllocator); + layer_destroy_messenger_callback(my_data->report_data, messenger, pAllocator); + if (threadChecks) { + finishReadObject(my_data, instance); + finishWriteObject(my_data, messenger); + } else { + finishMultiThread(); + } +} + +// VK_EXT_debug_report commands VKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo, const VkAllocationCallbacks *pAllocator, @@ -284,7 +349,11 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(VkInstance instance, VkResult result = my_data->instance_dispatch_table->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback); if (VK_SUCCESS == result) { - result = layer_create_msg_callback(my_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback); + result = layer_create_report_callback(my_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback); + // If something happened during this call, clean up the message callback that was created earlier in the lower levels + if (VK_SUCCESS != result) { + my_data->instance_dispatch_table->DestroyDebugReportCallbackEXT(instance, *pMsgCallback, pAllocator); + } } if (threadChecks) { finishReadObject(my_data, instance); @@ -303,7 +372,7 @@ VKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance, Vk startWriteObject(my_data, callback); } my_data->instance_dispatch_table->DestroyDebugReportCallbackEXT(instance, callback, pAllocator); - layer_destroy_msg_callback(my_data->report_data, callback, pAllocator); + layer_destroy_report_callback(my_data->report_data, callback, pAllocator); if (threadChecks) { finishReadObject(my_data, instance); finishWriteObject(my_data, callback); @@ -400,6 +469,23 @@ VKAPI_ATTR void VKAPI_CALL FreeCommandBuffers(VkDevice device, VkCommandPool com } // namespace threading // vk_layer_logging.h expects these to be defined +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugUtilsMessengerEXT(VkInstance instance, + const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo, + const VkAllocationCallbacks *pAllocator, + VkDebugUtilsMessengerEXT *pMessenger) { + return threading::CreateDebugUtilsMessengerEXT(instance, pCreateInfo, pAllocator, pMessenger); +} + +VKAPI_ATTR void VKAPI_CALL vkDestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger, + const VkAllocationCallbacks *pAllocator) { + threading::DestroyDebugUtilsMessengerEXT(instance, messenger, pAllocator); +} + +VKAPI_ATTR void VKAPI_CALL vkSubmitDebugUtilsMessageEXT(VkInstance instance, VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageTypes, + const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData) { + threading::SubmitDebugUtilsMessageEXT(instance, messageSeverity, messageTypes, pCallbackData); +} VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo, diff --git a/layers/threading.h b/layers/threading.h index e2301d00..70814a53 100644 --- a/layers/threading.h +++ b/layers/threading.h @@ -228,13 +228,19 @@ struct layer_data { debug_report_data *report_data; std::vector<VkDebugReportCallbackEXT> logging_callback; + std::vector<VkDebugUtilsMessengerEXT> logging_messenger; VkLayerDispatchTable *device_dispatch_table; VkLayerInstanceDispatchTable *instance_dispatch_table; + // The following are for keeping track of the temporary callbacks that can // be used in vkCreateInstance and vkDestroyInstance: - uint32_t num_tmp_callbacks; - VkDebugReportCallbackCreateInfoEXT *tmp_dbg_create_infos; - VkDebugReportCallbackEXT *tmp_callbacks; + uint32_t num_tmp_report_callbacks; + VkDebugReportCallbackCreateInfoEXT *tmp_report_create_infos; + VkDebugReportCallbackEXT *tmp_report_callbacks; + uint32_t num_tmp_debug_messengers; + VkDebugUtilsMessengerCreateInfoEXT *tmp_messenger_create_infos; + VkDebugUtilsMessengerEXT *tmp_debug_messengers; + counter<VkCommandBuffer> c_VkCommandBuffer; counter<VkDevice> c_VkDevice; counter<VkInstance> c_VkInstance; @@ -270,15 +276,19 @@ struct layer_data { counter<VkDescriptorUpdateTemplateKHR> c_VkDescriptorUpdateTemplateKHR; counter<VkValidationCacheEXT> c_VkValidationCacheEXT; counter<VkSamplerYcbcrConversionKHR> c_VkSamplerYcbcrConversionKHR; + counter<VkDebugUtilsMessengerEXT> c_VkDebugUtilsMessengerEXT; #else // DISTINCT_NONDISPATCHABLE_HANDLES counter<uint64_t> c_uint64_t; #endif // DISTINCT_NONDISPATCHABLE_HANDLES layer_data() : report_data(nullptr), - num_tmp_callbacks(0), - tmp_dbg_create_infos(nullptr), - tmp_callbacks(nullptr), + num_tmp_report_callbacks(0), + tmp_report_create_infos(nullptr), + tmp_report_callbacks(nullptr), + num_tmp_debug_messengers(0), + tmp_messenger_create_infos(nullptr), + tmp_debug_messengers(nullptr), c_VkCommandBuffer("VkCommandBuffer", VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT), c_VkDevice("VkDevice", VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT), c_VkInstance("VkInstance", VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT), @@ -314,7 +324,9 @@ struct layer_data { c_VkSwapchainKHR("VkSwapchainKHR", VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT), c_VkDescriptorUpdateTemplateKHR("VkDescriptorUpdateTemplateKHR", VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT), - c_VkSamplerYcbcrConversionKHR("VkSamplerYcbcrConversionKHR", VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT) + c_VkSamplerYcbcrConversionKHR("VkSamplerYcbcrConversionKHR", + VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT), + c_VkDebugUtilsMessengerEXT("VkDebugUtilsMessengerEXT", VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT) #else // DISTINCT_NONDISPATCHABLE_HANDLES c_uint64_t("NON_DISPATCHABLE_HANDLE", VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT) #endif // DISTINCT_NONDISPATCHABLE_HANDLES @@ -365,6 +377,7 @@ WRAPPER(VkSwapchainKHR) WRAPPER(VkDescriptorUpdateTemplateKHR) WRAPPER(VkValidationCacheEXT) WRAPPER(VkSamplerYcbcrConversionKHR) +WRAPPER(VkDebugUtilsMessengerEXT) #else // DISTINCT_NONDISPATCHABLE_HANDLES WRAPPER(uint64_t) #endif // DISTINCT_NONDISPATCHABLE_HANDLES diff --git a/layers/unique_objects.cpp b/layers/unique_objects.cpp index 37003700..702f07b1 100644 --- a/layers/unique_objects.cpp +++ b/layers/unique_objects.cpp @@ -59,7 +59,9 @@ namespace unique_objects { static uint32_t loader_layer_if_version = CURRENT_LOADER_LAYER_INTERFACE_VERSION; static void initUniqueObjects(instance_layer_data *instance_data, const VkAllocationCallbacks *pAllocator) { - layer_debug_actions(instance_data->report_data, instance_data->logging_callback, pAllocator, "google_unique_objects"); + layer_debug_report_actions(instance_data->report_data, instance_data->logging_callback, pAllocator, "google_unique_objects"); + layer_debug_messenger_actions(instance_data->report_data, instance_data->logging_messenger, pAllocator, + "google_unique_objects"); } // Check enabled instance extensions against supported instance extension whitelist @@ -118,17 +120,27 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreat layer_init_instance_dispatch_table(*pInstance, &instance_data->dispatch_table, fpGetInstanceProcAddr); instance_data->instance = *pInstance; - instance_data->report_data = debug_report_create_instance( + instance_data->report_data = debug_utils_create_instance( &instance_data->dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames); // Set up temporary debug callbacks to output messages at CreateInstance-time - if (!layer_copy_tmp_callbacks(pCreateInfo->pNext, &instance_data->num_tmp_callbacks, &instance_data->tmp_dbg_create_infos, - &instance_data->tmp_callbacks)) { - if (instance_data->num_tmp_callbacks > 0) { - if (layer_enable_tmp_callbacks(instance_data->report_data, instance_data->num_tmp_callbacks, - instance_data->tmp_dbg_create_infos, instance_data->tmp_callbacks)) { - layer_free_tmp_callbacks(instance_data->tmp_dbg_create_infos, instance_data->tmp_callbacks); - instance_data->num_tmp_callbacks = 0; + if (!layer_copy_tmp_debug_messengers(pCreateInfo->pNext, &instance_data->num_tmp_debug_messengers, + &instance_data->tmp_messenger_create_infos, &instance_data->tmp_debug_messengers)) { + if (instance_data->num_tmp_debug_messengers > 0) { + if (layer_enable_tmp_debug_messengers(instance_data->report_data, instance_data->num_tmp_debug_messengers, + instance_data->tmp_messenger_create_infos, instance_data->tmp_debug_messengers)) { + layer_free_tmp_debug_messengers(instance_data->tmp_messenger_create_infos, instance_data->tmp_debug_messengers); + instance_data->num_tmp_debug_messengers = 0; + } + } + } + if (!layer_copy_tmp_report_callbacks(pCreateInfo->pNext, &instance_data->num_tmp_report_callbacks, + &instance_data->tmp_report_create_infos, &instance_data->tmp_report_callbacks)) { + if (instance_data->num_tmp_report_callbacks > 0) { + if (layer_enable_tmp_report_callbacks(instance_data->report_data, instance_data->num_tmp_report_callbacks, + instance_data->tmp_report_create_infos, instance_data->tmp_report_callbacks)) { + layer_free_tmp_report_callbacks(instance_data->tmp_report_create_infos, instance_data->tmp_report_callbacks); + instance_data->num_tmp_report_callbacks = 0; } } } @@ -137,10 +149,17 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreat InstanceExtensionWhitelist(pCreateInfo, *pInstance); // Disable and free tmp callbacks, no longer necessary - if (instance_data->num_tmp_callbacks > 0) { - layer_disable_tmp_callbacks(instance_data->report_data, instance_data->num_tmp_callbacks, instance_data->tmp_callbacks); - layer_free_tmp_callbacks(instance_data->tmp_dbg_create_infos, instance_data->tmp_callbacks); - instance_data->num_tmp_callbacks = 0; + if (instance_data->num_tmp_debug_messengers > 0) { + layer_disable_tmp_debug_messengers(instance_data->report_data, instance_data->num_tmp_debug_messengers, + instance_data->tmp_debug_messengers); + layer_free_tmp_debug_messengers(instance_data->tmp_messenger_create_infos, instance_data->tmp_debug_messengers); + instance_data->num_tmp_debug_messengers = 0; + } + if (instance_data->num_tmp_report_callbacks > 0) { + layer_disable_tmp_report_callbacks(instance_data->report_data, instance_data->num_tmp_report_callbacks, + instance_data->tmp_report_callbacks); + layer_free_tmp_report_callbacks(instance_data->tmp_report_create_infos, instance_data->tmp_report_callbacks); + instance_data->num_tmp_report_callbacks = 0; } return result; @@ -153,13 +172,18 @@ VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocati disp_table->DestroyInstance(instance, pAllocator); // Clean up logging callback, if any + while (instance_data->logging_messenger.size() > 0) { + VkDebugUtilsMessengerEXT messenger = instance_data->logging_messenger.back(); + layer_destroy_messenger_callback(instance_data->report_data, messenger, pAllocator); + instance_data->logging_messenger.pop_back(); + } while (instance_data->logging_callback.size() > 0) { VkDebugReportCallbackEXT callback = instance_data->logging_callback.back(); - layer_destroy_msg_callback(instance_data->report_data, callback, pAllocator); + layer_destroy_report_callback(instance_data->report_data, callback, pAllocator); instance_data->logging_callback.pop_back(); } - layer_debug_report_destroy_instance(instance_data->report_data); + layer_debug_utils_destroy_instance(instance_data->report_data); FreeLayerDataPtr(key, instance_layer_data_map); } @@ -185,7 +209,7 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDevice } layer_data *my_device_data = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map); - my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice); + my_device_data->report_data = layer_debug_utils_create_device(my_instance_data->report_data, *pDevice); // Setup layer's device dispatch table layer_init_device_dispatch_table(*pDevice, &my_device_data->dispatch_table, fpGetDeviceProcAddr); @@ -202,7 +226,7 @@ VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCall dispatch_key key = get_dispatch_key(device); layer_data *dev_data = GetLayerDataPtr(key, layer_data_map); - layer_debug_report_destroy_device(device); + layer_debug_utils_destroy_device(device); dev_data->dispatch_table.DestroyDevice(device, pAllocator); FreeLayerDataPtr(key, layer_data_map); @@ -877,6 +901,37 @@ VKAPI_ATTR VkResult VKAPI_CALL DebugMarkerSetObjectNameEXT(VkDevice device, cons return result; } +// VK_EXT_debug_utils +VKAPI_ATTR VkResult VKAPI_CALL SetDebugUtilsObjectTagEXT(VkDevice device, const VkDebugUtilsObjectTagInfoEXT *pTagInfo) { + layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); + auto local_tag_info = new safe_VkDebugUtilsObjectTagInfoEXT(pTagInfo); + { + std::lock_guard<std::mutex> lock(global_lock); + auto it = device_data->unique_id_mapping.find(reinterpret_cast<uint64_t &>(local_tag_info->objectHandle)); + if (it != device_data->unique_id_mapping.end()) { + local_tag_info->objectHandle = it->second; + } + } + VkResult result = device_data->dispatch_table.SetDebugUtilsObjectTagEXT( + device, reinterpret_cast<const VkDebugUtilsObjectTagInfoEXT *>(local_tag_info)); + return result; +} + +VKAPI_ATTR VkResult VKAPI_CALL SetDebugUtilsObjectNameEXT(VkDevice device, const VkDebugUtilsObjectNameInfoEXT *pNameInfo) { + layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); + auto local_name_info = new safe_VkDebugUtilsObjectNameInfoEXT(pNameInfo); + { + std::lock_guard<std::mutex> lock(global_lock); + auto it = device_data->unique_id_mapping.find(reinterpret_cast<uint64_t &>(local_name_info->objectHandle)); + if (it != device_data->unique_id_mapping.end()) { + local_name_info->objectHandle = it->second; + } + } + VkResult result = device_data->dispatch_table.SetDebugUtilsObjectNameEXT( + device, reinterpret_cast<const VkDebugUtilsObjectNameInfoEXT *>(local_name_info)); + return result; +} + } // namespace unique_objects VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, diff --git a/layers/unique_objects.h b/layers/unique_objects.h index 3dd3a797..0a03234c 100644 --- a/layers/unique_objects.h +++ b/layers/unique_objects.h @@ -50,12 +50,17 @@ struct instance_layer_data { debug_report_data *report_data; std::vector<VkDebugReportCallbackEXT> logging_callback; + std::vector<VkDebugUtilsMessengerEXT> logging_messenger; VkLayerInstanceDispatchTable dispatch_table = {}; - // The following are for keeping track of the temporary callbacks that can be used in vkCreateInstance and vkDestroyInstance: - uint32_t num_tmp_callbacks; - VkDebugReportCallbackCreateInfoEXT *tmp_dbg_create_infos; - VkDebugReportCallbackEXT *tmp_callbacks; + // The following are for keeping track of the temporary callbacks that can + // be used in vkCreateInstance and vkDestroyInstance: + uint32_t num_tmp_report_callbacks; + VkDebugReportCallbackCreateInfoEXT *tmp_report_create_infos; + VkDebugReportCallbackEXT *tmp_report_callbacks; + uint32_t num_tmp_debug_messengers; + VkDebugUtilsMessengerCreateInfoEXT *tmp_messenger_create_infos; + VkDebugUtilsMessengerEXT *tmp_debug_messengers; }; struct layer_data { diff --git a/layers/vk_layer_config.cpp b/layers/vk_layer_config.cpp index b1b09d4c..51f42780 100644 --- a/layers/vk_layer_config.cpp +++ b/layers/vk_layer_config.cpp @@ -248,31 +248,74 @@ void ConfigFile::parseFile(const char *filename) { } } -VK_LAYER_EXPORT void print_msg_flags(VkFlags msgFlags, char *msg_flags) { +VK_LAYER_EXPORT void PrintMessageFlags(VkFlags vk_flags, char *msg_flags) { bool separator = false; msg_flags[0] = 0; - if (msgFlags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) { + if (vk_flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) { strcat(msg_flags, "DEBUG"); separator = true; } - if (msgFlags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) { + if (vk_flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) { if (separator) strcat(msg_flags, ","); strcat(msg_flags, "INFO"); separator = true; } - if (msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT) { + if (vk_flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) { if (separator) strcat(msg_flags, ","); strcat(msg_flags, "WARN"); separator = true; } - if (msgFlags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) { + if (vk_flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) { if (separator) strcat(msg_flags, ","); strcat(msg_flags, "PERF"); separator = true; } - if (msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT) { + if (vk_flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) { if (separator) strcat(msg_flags, ","); strcat(msg_flags, "ERROR"); } } + +VK_LAYER_EXPORT void PrintMessageSeverity(VkFlags vk_flags, char *msg_flags) { + bool separator = false; + + msg_flags[0] = 0; + if (vk_flags & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) { + strcat(msg_flags, "VERBOSE"); + separator = true; + } + if (vk_flags & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) { + if (separator) strcat(msg_flags, ","); + strcat(msg_flags, "INFO"); + separator = true; + } + if (vk_flags & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) { + if (separator) strcat(msg_flags, ","); + strcat(msg_flags, "WARN"); + separator = true; + } + if (vk_flags & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) { + if (separator) strcat(msg_flags, ","); + strcat(msg_flags, "ERROR"); + } +} + +VK_LAYER_EXPORT void PrintMessageType(VkFlags vk_flags, char *msg_flags) { + bool separator = false; + + msg_flags[0] = 0; + if (vk_flags & VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT) { + strcat(msg_flags, "GEN"); + separator = true; + } + if (vk_flags & VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT) { + strcat(msg_flags, "SPEC"); + separator = true; + } + if (vk_flags & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) { + if (separator) strcat(msg_flags, ","); + strcat(msg_flags, "PERF"); + separator = true; + } +} diff --git a/layers/vk_layer_config.h b/layers/vk_layer_config.h index b12ba50d..e0b9d326 100644 --- a/layers/vk_layer_config.h +++ b/layers/vk_layer_config.h @@ -63,7 +63,9 @@ VK_LAYER_EXPORT VkFlags GetLayerOptionFlags(std::string _option, std::unordered_ uint32_t option_default); VK_LAYER_EXPORT void setLayerOption(const char *_option, const char *_val); -VK_LAYER_EXPORT void print_msg_flags(VkFlags msgFlags, char *msg_flags); +VK_LAYER_EXPORT void PrintMessageFlags(VkFlags vk_flags, char *msg_flags); +VK_LAYER_EXPORT void PrintMessageSeverity(VkFlags vk_flags, char *msg_flags); +VK_LAYER_EXPORT void PrintMessageType(VkFlags vk_flags, char *msg_flags); #ifdef __cplusplus } diff --git a/layers/vk_layer_logging.h b/layers/vk_layer_logging.h index 559b5a45..61e109af 100644 --- a/layers/vk_layer_logging.h +++ b/layers/vk_layer_logging.h @@ -1,6 +1,6 @@ -/* Copyright (c) 2015-2016 The Khronos Group Inc. - * Copyright (c) 2015-2016 Valve Corporation - * Copyright (c) 2015-2016 LunarG, Inc. +/* Copyright (c) 2015-2017 The Khronos Group Inc. + * Copyright (c) 2015-2017 Valve Corporation + * Copyright (c) 2015-2017 LunarG, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ * * Author: Courtney Goeltzenleuchter <courtney@LunarG.com> * Author: Tobin Ehlis <tobin@lunarg.com> + * Author: Mark Young <marky@lunarg.com> * */ @@ -28,6 +29,7 @@ #include "vk_layer_table.h" #include "vk_loader_platform.h" #include "vulkan/vk_layer.h" +#include "vk_object_types.h" #include <signal.h> #include <cinttypes> #include <stdarg.h> @@ -35,51 +37,140 @@ #include <stdio.h> #include <unordered_map> #include <vector> +#include <sstream> +#include <string> + +// TODO: Could be autogenerated for the specific handles for extra type safety... +template <typename HANDLE_T> +static inline uint64_t HandleToUint64(HANDLE_T *h) { + return reinterpret_cast<uint64_t>(h); +} + +static inline uint64_t HandleToUint64(uint64_t h) { return h; } + +// Data we store per label for logging +typedef struct _LoggingLabelData { + std::string name; + float color[4]; +} LoggingLabelData; typedef struct _debug_report_data { VkLayerDbgFunctionNode *debug_callback_list; VkLayerDbgFunctionNode *default_debug_callback_list; - VkFlags active_flags; + VkDebugUtilsMessageSeverityFlagsEXT active_severities; + VkDebugUtilsMessageTypeFlagsEXT active_types; bool g_DEBUG_REPORT; + bool g_DEBUG_UTILS; std::unordered_map<uint64_t, std::string> *debugObjectNameMap; + std::unordered_map<uint64_t, std::string> *debugUtilsObjectNameMap; + std::unordered_map<VkQueue, std::vector<LoggingLabelData>> *debugUtilsQueueLabels; + bool queueLabelHasInsert; + std::unordered_map<VkCommandBuffer, std::vector<LoggingLabelData>> *debugUtilsCmdBufLabels; + bool cmdBufLabelHasInsert; } debug_report_data; template debug_report_data *GetLayerDataPtr<debug_report_data>(void *data_key, std::unordered_map<void *, debug_report_data *> &data_map); +static inline void DebugReportFlagsToAnnotFlags(VkDebugReportFlagsEXT dr_flags, bool default_flag_is_spec, + VkDebugUtilsMessageSeverityFlagsEXT *da_severity, + VkDebugUtilsMessageTypeFlagsEXT *da_type) { + // All layer warnings are spec warnings currently. At least as far as anything not specifically + // called out. In the future, we'll label things using the new split severity and type values. + *da_type = VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT; + *da_severity = 0; + if ((dr_flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) != 0) { + *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT; + *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT; + } + if ((dr_flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) != 0) { + *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT; + *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT; + } + if ((dr_flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) != 0) { + *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT; + *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; + } + if ((dr_flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) != 0) { + *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT; + } + if ((dr_flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) != 0) { + *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; + } +} + // Forward Declarations -static inline bool debug_report_log_msg(const debug_report_data *debug_data, VkFlags msgFlags, - VkDebugReportObjectTypeEXT objectType, uint64_t srcObject, size_t location, int32_t msgCode, - const char *pLayerPrefix, const char *pMsg); +static inline bool debug_log_msg(const debug_report_data *debug_data, VkFlags msg_flags, VkDebugReportObjectTypeEXT object_type, + uint64_t src_object, size_t location, int32_t msg_code, const char *layer_prefix, + const char *message); // Add a debug message callback node structure to the specified callback linked list -static inline void AddDebugMessageCallback(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head, - VkLayerDbgFunctionNode *new_node) { +static inline void AddDebugCallbackNode(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head, + VkLayerDbgFunctionNode *new_node) { new_node->pNext = *list_head; *list_head = new_node; } +// Remove specified debug messenger node structure from the specified linked list +static inline void RemoveDebugUtilsMessenger(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head, + VkDebugUtilsMessengerEXT messenger) { + VkLayerDbgFunctionNode *cur_callback = *list_head; + VkLayerDbgFunctionNode *prev_callback = cur_callback; + bool matched = false; + VkFlags local_severities = 0; + VkFlags local_types = 0; + + while (cur_callback) { + if (cur_callback->is_messenger && cur_callback->messenger.messenger == messenger) { + matched = true; + prev_callback->pNext = cur_callback->pNext; + if (*list_head == cur_callback) { + *list_head = cur_callback->pNext; + } + debug_log_msg(debug_data, VK_DEBUG_REPORT_DEBUG_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT, + reinterpret_cast<uint64_t &>(cur_callback->messenger.messenger), 0, 0, "DebugUtilsMessenger", + "Destroyed messenger\n"); + } else { + matched = false; + local_severities |= cur_callback->messenger.messageSeverity; + local_types |= cur_callback->messenger.messageType; + } + prev_callback = cur_callback; + cur_callback = cur_callback->pNext; + if (matched) { + free(prev_callback); + } + } + debug_data->active_severities = local_severities; + debug_data->active_types = local_types; +} + // Remove specified debug message callback node structure from the specified callback linked list -static inline void RemoveDebugMessageCallback(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head, - VkDebugReportCallbackEXT callback) { +static inline void RemoveDebugUtilsMessageCallback(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head, + VkDebugReportCallbackEXT callback) { VkLayerDbgFunctionNode *cur_callback = *list_head; VkLayerDbgFunctionNode *prev_callback = cur_callback; bool matched = false; - VkFlags local_flags = 0; + VkFlags local_severities = 0; + VkFlags local_types = 0; while (cur_callback) { - if (cur_callback->msgCallback == callback) { + if (!cur_callback->is_messenger && cur_callback->report.msgCallback == callback) { matched = true; prev_callback->pNext = cur_callback->pNext; if (*list_head == cur_callback) { *list_head = cur_callback->pNext; } - debug_report_log_msg(debug_data, VK_DEBUG_REPORT_DEBUG_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT, - reinterpret_cast<uint64_t &>(cur_callback->msgCallback), 0, 0, "DebugReport", - "Destroyed callback\n"); + debug_log_msg(debug_data, VK_DEBUG_REPORT_DEBUG_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT, + reinterpret_cast<uint64_t &>(cur_callback->report.msgCallback), 0, 0, "DebugReport", + "Destroyed callback\n"); } else { matched = false; - local_flags |= cur_callback->msgFlags; + VkFlags this_severities = 0; + VkFlags this_types = 0; + DebugReportFlagsToAnnotFlags(cur_callback->report.msgFlags, true, &this_severities, &this_types); + local_severities |= this_severities; + local_types |= this_types; } prev_callback = cur_callback; cur_callback = cur_callback->pNext; @@ -87,7 +178,8 @@ static inline void RemoveDebugMessageCallback(debug_report_data *debug_data, VkL free(prev_callback); } } - debug_data->active_flags = local_flags; + debug_data->active_severities = local_severities; + debug_data->active_types = local_types; } // Removes all debug callback function nodes from the specified callback linked lists and frees their resources @@ -97,9 +189,15 @@ static inline void RemoveAllMessageCallbacks(debug_report_data *debug_data, VkLa while (current_callback) { prev_callback = current_callback->pNext; - debug_report_log_msg(debug_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT, - (uint64_t)current_callback->msgCallback, 0, 0, "DebugReport", - "Debug Report callbacks not removed before DestroyInstance"); + if (!current_callback->is_messenger) { + debug_log_msg(debug_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT, + (uint64_t)current_callback->report.msgCallback, 0, 0, "DebugReport", + "Debug Report callbacks not removed before DestroyInstance"); + } else { + debug_log_msg(debug_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT, + (uint64_t)current_callback->messenger.messenger, 0, 0, "Messenger", + "Debug messengers not removed before DestroyInstance"); + } free(current_callback); current_callback = prev_callback; } @@ -107,46 +205,222 @@ static inline void RemoveAllMessageCallbacks(debug_report_data *debug_data, VkLa } // Utility function to handle reporting -static inline bool debug_report_log_msg(const debug_report_data *debug_data, VkFlags msgFlags, - VkDebugReportObjectTypeEXT objectType, uint64_t srcObject, size_t location, int32_t msgCode, - const char *pLayerPrefix, const char *pMsg) { +static inline bool debug_log_msg(const debug_report_data *debug_data, VkFlags msg_flags, VkDebugReportObjectTypeEXT object_type, + uint64_t src_object, size_t location, int32_t msg_code, const char *layer_prefix, + const char *message) { bool bail = false; - VkLayerDbgFunctionNode *pTrav = NULL; + VkLayerDbgFunctionNode *layer_dbg_node = NULL; if (debug_data->debug_callback_list != NULL) { - pTrav = debug_data->debug_callback_list; + layer_dbg_node = debug_data->debug_callback_list; } else { - pTrav = debug_data->default_debug_callback_list; + layer_dbg_node = debug_data->default_debug_callback_list; } - while (pTrav) { - if (pTrav->msgFlags & msgFlags) { - auto it = debug_data->debugObjectNameMap->find(srcObject); + VkDebugUtilsMessageSeverityFlagsEXT severity; + VkDebugUtilsMessageTypeFlagsEXT types; + VkDebugUtilsMessengerCallbackDataEXT callback_data; + VkDebugUtilsObjectNameInfoEXT object_name_info; + + // Convert the info to the VK_EXT_debug_utils form in case we need it. + DebugReportFlagsToAnnotFlags(msg_flags, true, &severity, &types); + object_name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT; + object_name_info.pNext = NULL; + object_name_info.objectType = convertDebugReportObjectToCoreObject(object_type); + object_name_info.objectHandle = (uint64_t)(uintptr_t)src_object; + object_name_info.pObjectName = NULL; + + callback_data.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT; + callback_data.pNext = NULL; + callback_data.flags = 0; + callback_data.pMessageIdName = layer_prefix; + callback_data.messageIdNumber = msg_code; + callback_data.pMessage = message; + callback_data.queueLabelCount = 0; + callback_data.pQueueLabels = NULL; + callback_data.cmdBufLabelCount = 0; + callback_data.pCmdBufLabels = NULL; + callback_data.objectCount = 1; + callback_data.pObjects = &object_name_info; + + VkDebugUtilsLabelEXT *queue_labels = nullptr; + VkDebugUtilsLabelEXT *cmd_buf_labels = nullptr; + std::string new_debug_report_message = ""; + std::ostringstream oss; + oss << "Object: 0x" << std::hex << src_object; + + if (0 != src_object) { + // If this is a queue, add any queue labels to the callback data. + if (VK_OBJECT_TYPE_QUEUE == object_name_info.objectType) { + auto label_iter = debug_data->debugUtilsQueueLabels->find(reinterpret_cast<VkQueue>(src_object)); + if (label_iter != debug_data->debugUtilsQueueLabels->end()) { + queue_labels = new VkDebugUtilsLabelEXT[label_iter->second.size()]; + if (nullptr != queue_labels) { + // Record the labels, but record them in reverse order since we want the + // most recent at the top. + uint32_t label_size = static_cast<uint32_t>(label_iter->second.size()); + uint32_t last_index = label_size - 1; + for (uint32_t label = 0; label < label_size; ++label) { + queue_labels[last_index - label].sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT; + queue_labels[last_index - label].pNext = nullptr; + queue_labels[last_index - label].pLabelName = label_iter->second[label].name.c_str(); + queue_labels[last_index - label].color[0] = label_iter->second[label].color[0]; + queue_labels[last_index - label].color[1] = label_iter->second[label].color[1]; + queue_labels[last_index - label].color[2] = label_iter->second[label].color[2]; + queue_labels[last_index - label].color[3] = label_iter->second[label].color[3]; + } + callback_data.queueLabelCount = label_size; + callback_data.pQueueLabels = queue_labels; + } + } + // If this is a command buffer, add any command buffer labels to the callback data. + } else if (VK_OBJECT_TYPE_COMMAND_BUFFER == object_name_info.objectType) { + auto label_iter = debug_data->debugUtilsCmdBufLabels->find(reinterpret_cast<VkCommandBuffer>(src_object)); + if (label_iter != debug_data->debugUtilsCmdBufLabels->end()) { + cmd_buf_labels = new VkDebugUtilsLabelEXT[label_iter->second.size()]; + if (nullptr != cmd_buf_labels) { + // Record the labels, but record them in reverse order since we want the + // most recent at the top. + uint32_t label_size = static_cast<uint32_t>(label_iter->second.size()); + uint32_t last_index = label_size - 1; + for (uint32_t label = 0; label < label_size; ++label) { + cmd_buf_labels[last_index - label].sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT; + cmd_buf_labels[last_index - label].pNext = nullptr; + cmd_buf_labels[last_index - label].pLabelName = label_iter->second[label].name.c_str(); + cmd_buf_labels[last_index - label].color[0] = label_iter->second[label].color[0]; + cmd_buf_labels[last_index - label].color[1] = label_iter->second[label].color[1]; + cmd_buf_labels[last_index - label].color[2] = label_iter->second[label].color[2]; + cmd_buf_labels[last_index - label].color[3] = label_iter->second[label].color[3]; + } + callback_data.cmdBufLabelCount = label_size; + callback_data.pCmdBufLabels = cmd_buf_labels; + } + } + } + // Look for any debug utils or marker names to use for this object + callback_data.pObjects[0].pObjectName = NULL; + auto utils_name_iter = debug_data->debugUtilsObjectNameMap->find(src_object); + if (utils_name_iter != debug_data->debugUtilsObjectNameMap->end()) { + callback_data.pObjects[0].pObjectName = utils_name_iter->second.c_str(); + } else { + auto marker_name_iter = debug_data->debugObjectNameMap->find(src_object); + if (marker_name_iter != debug_data->debugObjectNameMap->end()) { + callback_data.pObjects[0].pObjectName = marker_name_iter->second.c_str(); + } + } + if (NULL != callback_data.pObjects[0].pObjectName) { + oss << " (Name = " << callback_data.pObjects[0].pObjectName << ")"; + } + } + new_debug_report_message += oss.str(); + new_debug_report_message += " | "; + new_debug_report_message += message; + + while (layer_dbg_node) { + if (!layer_dbg_node->is_messenger && (layer_dbg_node->report.msgFlags & msg_flags) && + layer_dbg_node->report.pfnMsgCallback(msg_flags, object_type, src_object, location, msg_code, layer_prefix, + new_debug_report_message.c_str(), layer_dbg_node->pUserData)) { + bail = true; + } else if (layer_dbg_node->is_messenger && (layer_dbg_node->messenger.messageSeverity & severity) && + (layer_dbg_node->messenger.messageType & types) && + layer_dbg_node->messenger.pfnUserCallback(static_cast<VkDebugUtilsMessageSeverityFlagBitsEXT>(severity), types, + &callback_data, layer_dbg_node->pUserData)) { + bail = true; + } + layer_dbg_node = layer_dbg_node->pNext; + } + + if (nullptr != queue_labels) { + delete[] queue_labels; + } + if (nullptr != cmd_buf_labels) { + delete[] cmd_buf_labels; + } + + return bail; +} + +static inline void DebugAnnotFlagsToReportFlags(VkDebugUtilsMessageSeverityFlagBitsEXT da_severity, + VkDebugUtilsMessageTypeFlagsEXT da_type, VkDebugReportFlagsEXT *dr_flags) { + *dr_flags = 0; + + if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) != 0) { + *dr_flags |= VK_DEBUG_REPORT_ERROR_BIT_EXT; + } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) != 0) { + if ((da_type & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) != 0) { + *dr_flags |= VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; + } else { + *dr_flags |= VK_DEBUG_REPORT_WARNING_BIT_EXT; + } + } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) != 0) { + *dr_flags |= VK_DEBUG_REPORT_INFORMATION_BIT_EXT; + } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) != 0) { + *dr_flags |= VK_DEBUG_REPORT_DEBUG_BIT_EXT; + } +} + +static inline bool debug_messenger_log_msg(const debug_report_data *debug_data, + VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, + VkDebugUtilsMessageTypeFlagsEXT message_type, + VkDebugUtilsMessengerCallbackDataEXT *callback_data) { + bool bail = false; + VkLayerDbgFunctionNode *layer_dbg_node = NULL; + + if (debug_data->debug_callback_list != NULL) { + layer_dbg_node = debug_data->debug_callback_list; + } else { + layer_dbg_node = debug_data->default_debug_callback_list; + } + + VkDebugReportFlagsEXT object_flags = 0; + + DebugAnnotFlagsToReportFlags(message_severity, message_type, &object_flags); + + while (layer_dbg_node) { + if (layer_dbg_node->is_messenger && (layer_dbg_node->messenger.messageSeverity & message_severity) && + (layer_dbg_node->messenger.messageType & message_type)) { + // Loop through each object and give it the proper name if it was set. + for (uint32_t obj = 0; obj < callback_data->objectCount; obj++) { + auto it = debug_data->debugUtilsObjectNameMap->find(callback_data->pObjects[obj].objectHandle); + if (it == debug_data->debugUtilsObjectNameMap->end()) { + continue; + } + callback_data->pObjects[obj].pObjectName = it->second.c_str(); + } + if (layer_dbg_node->messenger.pfnUserCallback(message_severity, message_type, callback_data, + layer_dbg_node->pUserData)) { + bail = true; + } + } else if (!layer_dbg_node->is_messenger && layer_dbg_node->report.msgFlags & object_flags) { + auto it = debug_data->debugObjectNameMap->find(callback_data->pObjects[0].objectHandle); + VkDebugReportObjectTypeEXT object_type = get_debug_report_enum[callback_data->pObjects[0].objectType]; if (it == debug_data->debugObjectNameMap->end()) { - if (pTrav->pfnMsgCallback(msgFlags, objectType, srcObject, location, msgCode, pLayerPrefix, pMsg, - pTrav->pUserData)) { + if (layer_dbg_node->report.pfnMsgCallback(object_flags, object_type, callback_data->pObjects[0].objectHandle, 0, + callback_data->messageIdNumber, callback_data->pMessageIdName, + callback_data->pMessage, layer_dbg_node->pUserData)) { bail = true; } } else { std::string newMsg = "SrcObject name = "; newMsg.append(it->second.c_str()); newMsg.append(" "); - newMsg.append(pMsg); - if (pTrav->pfnMsgCallback(msgFlags, objectType, srcObject, location, msgCode, pLayerPrefix, newMsg.c_str(), - pTrav->pUserData)) { + newMsg.append(callback_data->pMessage); + if (layer_dbg_node->report.pfnMsgCallback(object_flags, object_type, callback_data->pObjects[0].objectHandle, 0, + callback_data->messageIdNumber, callback_data->pMessageIdName, + newMsg.c_str(), layer_dbg_node->pUserData)) { bail = true; } } } - pTrav = pTrav->pNext; + layer_dbg_node = layer_dbg_node->pNext; } return bail; } -static inline debug_report_data *debug_report_create_instance( +static inline debug_report_data *debug_utils_create_instance( VkLayerInstanceDispatchTable *table, VkInstance inst, uint32_t extension_count, - const char *const *ppEnabledExtensions) // layer or extension name to be enabled + const char *const *enabled_extensions) // layer or extension name to be enabled { debug_report_data *debug_data = (debug_report_data *)malloc(sizeof(debug_report_data)); if (!debug_data) return NULL; @@ -154,78 +428,162 @@ static inline debug_report_data *debug_report_create_instance( memset(debug_data, 0, sizeof(debug_report_data)); for (uint32_t i = 0; i < extension_count; i++) { // TODO: Check other property fields - if (strcmp(ppEnabledExtensions[i], VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0) { + if (strcmp(enabled_extensions[i], VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0) { debug_data->g_DEBUG_REPORT = true; + } else if (strcmp(enabled_extensions[i], VK_EXT_DEBUG_UTILS_EXTENSION_NAME) == 0) { + debug_data->g_DEBUG_UTILS = true; } } debug_data->debugObjectNameMap = new std::unordered_map<uint64_t, std::string>; + debug_data->debugUtilsObjectNameMap = new std::unordered_map<uint64_t, std::string>; + debug_data->debugUtilsQueueLabels = new std::unordered_map<VkQueue, std::vector<LoggingLabelData>>; + debug_data->debugUtilsCmdBufLabels = new std::unordered_map<VkCommandBuffer, std::vector<LoggingLabelData>>; + debug_data->queueLabelHasInsert = false; + debug_data->cmdBufLabelHasInsert = false; return debug_data; } -static inline void layer_debug_report_destroy_instance(debug_report_data *debug_data) { +static inline void layer_debug_utils_destroy_instance(debug_report_data *debug_data) { if (debug_data) { RemoveAllMessageCallbacks(debug_data, &debug_data->default_debug_callback_list); RemoveAllMessageCallbacks(debug_data, &debug_data->debug_callback_list); delete debug_data->debugObjectNameMap; + delete debug_data->debugUtilsObjectNameMap; + delete debug_data->debugUtilsQueueLabels; + delete debug_data->debugUtilsCmdBufLabels; free(debug_data); } } -static inline debug_report_data *layer_debug_report_create_device(debug_report_data *instance_debug_data, VkDevice device) { +static inline debug_report_data *layer_debug_utils_create_device(debug_report_data *instance_debug_data, VkDevice device) { // DEBUG_REPORT shares data between Instance and Device, // so just return instance's data pointer return instance_debug_data; } -static inline void layer_debug_report_destroy_device(VkDevice device) { +static inline void layer_debug_utils_destroy_device(VkDevice device) { // Nothing to do since we're using instance data record } -static inline void layer_destroy_msg_callback(debug_report_data *debug_data, VkDebugReportCallbackEXT callback, - const VkAllocationCallbacks *pAllocator) { - RemoveDebugMessageCallback(debug_data, &debug_data->debug_callback_list, callback); - RemoveDebugMessageCallback(debug_data, &debug_data->default_debug_callback_list, callback); +static inline void layer_destroy_messenger_callback(debug_report_data *debug_data, VkDebugUtilsMessengerEXT messenger, + const VkAllocationCallbacks *allocator) { + RemoveDebugUtilsMessenger(debug_data, &debug_data->debug_callback_list, messenger); + RemoveDebugUtilsMessenger(debug_data, &debug_data->default_debug_callback_list, messenger); } -static inline VkResult layer_create_msg_callback(debug_report_data *debug_data, bool default_callback, - const VkDebugReportCallbackCreateInfoEXT *pCreateInfo, - const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pCallback) { +static inline VkResult layer_create_messenger_callback(debug_report_data *debug_data, bool default_callback, + const VkDebugUtilsMessengerCreateInfoEXT *create_info, + const VkAllocationCallbacks *allocator, + VkDebugUtilsMessengerEXT *messenger) { VkLayerDbgFunctionNode *pNewDbgFuncNode = (VkLayerDbgFunctionNode *)malloc(sizeof(VkLayerDbgFunctionNode)); if (!pNewDbgFuncNode) return VK_ERROR_OUT_OF_HOST_MEMORY; + memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode)); + pNewDbgFuncNode->is_messenger = true; // Handle of 0 is logging_callback so use allocated Node address as unique handle - if (!(*pCallback)) *pCallback = (VkDebugReportCallbackEXT)pNewDbgFuncNode; - pNewDbgFuncNode->msgCallback = *pCallback; - pNewDbgFuncNode->pfnMsgCallback = pCreateInfo->pfnCallback; - pNewDbgFuncNode->msgFlags = pCreateInfo->flags; - pNewDbgFuncNode->pUserData = pCreateInfo->pUserData; + if (!(*messenger)) *messenger = (VkDebugUtilsMessengerEXT)pNewDbgFuncNode; + pNewDbgFuncNode->messenger.messenger = *messenger; + pNewDbgFuncNode->messenger.pfnUserCallback = create_info->pfnUserCallback; + pNewDbgFuncNode->messenger.messageSeverity = create_info->messageSeverity; + pNewDbgFuncNode->messenger.messageType = create_info->messageType; + pNewDbgFuncNode->pUserData = create_info->pUserData; + debug_data->active_severities |= create_info->messageSeverity; + debug_data->active_types |= create_info->messageType; if (default_callback) { - AddDebugMessageCallback(debug_data, &debug_data->default_debug_callback_list, pNewDbgFuncNode); - debug_data->active_flags |= pCreateInfo->flags; + AddDebugCallbackNode(debug_data, &debug_data->default_debug_callback_list, pNewDbgFuncNode); } else { - AddDebugMessageCallback(debug_data, &debug_data->debug_callback_list, pNewDbgFuncNode); - debug_data->active_flags = pCreateInfo->flags; + AddDebugCallbackNode(debug_data, &debug_data->debug_callback_list, pNewDbgFuncNode); } - debug_report_log_msg(debug_data, VK_DEBUG_REPORT_DEBUG_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT, - (uint64_t)*pCallback, 0, 0, "DebugReport", "Added callback"); + VkDebugUtilsMessengerCallbackDataEXT callback_data = {}; + VkDebugUtilsObjectNameInfoEXT blank_object = {}; + callback_data.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT; + callback_data.pNext = NULL; + callback_data.flags = 0; + callback_data.pMessageIdName = "Layer Internal Message"; + callback_data.messageIdNumber = 0; + callback_data.pMessage = "Added messenger"; + callback_data.queueLabelCount = 0; + callback_data.pQueueLabels = NULL; + callback_data.cmdBufLabelCount = 0; + callback_data.pCmdBufLabels = NULL; + callback_data.objectCount = 1; + callback_data.pObjects = &blank_object; + blank_object.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT; + blank_object.pNext = NULL; + blank_object.objectType = VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT; + blank_object.objectHandle = HandleToUint64(*messenger); + blank_object.pObjectName = NULL; + debug_messenger_log_msg(debug_data, VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT, + VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, &callback_data); return VK_SUCCESS; } -static inline PFN_vkVoidFunction debug_report_get_instance_proc_addr(debug_report_data *debug_data, const char *funcName) { - if (!debug_data || !debug_data->g_DEBUG_REPORT) { - return NULL; +static inline void layer_destroy_report_callback(debug_report_data *debug_data, VkDebugReportCallbackEXT callback, + const VkAllocationCallbacks *allocator) { + RemoveDebugUtilsMessageCallback(debug_data, &debug_data->debug_callback_list, callback); + RemoveDebugUtilsMessageCallback(debug_data, &debug_data->default_debug_callback_list, callback); +} + +static inline VkResult layer_create_report_callback(debug_report_data *debug_data, bool default_callback, + const VkDebugReportCallbackCreateInfoEXT *create_info, + const VkAllocationCallbacks *allocator, VkDebugReportCallbackEXT *callback) { + VkLayerDbgFunctionNode *pNewDbgFuncNode = (VkLayerDbgFunctionNode *)malloc(sizeof(VkLayerDbgFunctionNode)); + if (!pNewDbgFuncNode) { + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode)); + pNewDbgFuncNode->is_messenger = false; + + // Handle of 0 is logging_callback so use allocated Node address as unique handle + if (!(*callback)) *callback = (VkDebugReportCallbackEXT)pNewDbgFuncNode; + pNewDbgFuncNode->report.msgCallback = *callback; + pNewDbgFuncNode->report.pfnMsgCallback = create_info->pfnCallback; + pNewDbgFuncNode->report.msgFlags = create_info->flags; + pNewDbgFuncNode->pUserData = create_info->pUserData; + + VkFlags local_severity = 0; + VkFlags local_type = 0; + DebugReportFlagsToAnnotFlags(create_info->flags, true, &local_severity, &local_type); + debug_data->active_severities |= local_severity; + debug_data->active_types |= local_type; + if (default_callback) { + AddDebugCallbackNode(debug_data, &debug_data->default_debug_callback_list, pNewDbgFuncNode); + } else { + AddDebugCallbackNode(debug_data, &debug_data->debug_callback_list, pNewDbgFuncNode); } - if (!strcmp(funcName, "vkCreateDebugReportCallbackEXT")) { - return (PFN_vkVoidFunction)vkCreateDebugReportCallbackEXT; + debug_log_msg(debug_data, VK_DEBUG_REPORT_DEBUG_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT, (uint64_t)*callback, 0, + 0, "DebugReport", "Added callback"); + return VK_SUCCESS; +} + +static inline PFN_vkVoidFunction debug_utils_get_instance_proc_addr(debug_report_data *debug_data, const char *func_name) { + if (!debug_data) { + return NULL; } - if (!strcmp(funcName, "vkDestroyDebugReportCallbackEXT")) { - return (PFN_vkVoidFunction)vkDestroyDebugReportCallbackEXT; + if (debug_data->g_DEBUG_REPORT) { + if (!strcmp(func_name, "vkCreateDebugReportCallbackEXT")) { + return (PFN_vkVoidFunction)vkCreateDebugReportCallbackEXT; + } + if (!strcmp(func_name, "vkDestroyDebugReportCallbackEXT")) { + return (PFN_vkVoidFunction)vkDestroyDebugReportCallbackEXT; + } + if (!strcmp(func_name, "vkDebugReportMessageEXT")) { + return (PFN_vkVoidFunction)vkDebugReportMessageEXT; + } } - if (!strcmp(funcName, "vkDebugReportMessageEXT")) { - return (PFN_vkVoidFunction)vkDebugReportMessageEXT; + if (debug_data->g_DEBUG_UTILS) { + if (!strcmp(func_name, "vkCreateDebugUtilsMessengerEXT")) { + return (PFN_vkVoidFunction)vkCreateDebugUtilsMessengerEXT; + } + if (!strcmp(func_name, "vkDestroyDebugUtilsMessengerEXT")) { + return (PFN_vkVoidFunction)vkDestroyDebugUtilsMessengerEXT; + } + if (!strcmp(func_name, "vkSubmitDebugUtilsMessageEXT")) { + return (PFN_vkVoidFunction)vkSubmitDebugUtilsMessageEXT; + } } return NULL; } @@ -235,8 +593,9 @@ static inline PFN_vkVoidFunction debug_report_get_instance_proc_addr(debug_repor // then allocates an array that can hold that many structs, as well as that // many VkDebugReportCallbackEXT handles. It then copies each // VkDebugReportCallbackCreateInfoEXT, and initializes each handle. -static inline VkResult layer_copy_tmp_callbacks(const void *pChain, uint32_t *num_callbacks, - VkDebugReportCallbackCreateInfoEXT **infos, VkDebugReportCallbackEXT **callbacks) { +static inline VkResult layer_copy_tmp_report_callbacks(const void *pChain, uint32_t *num_callbacks, + VkDebugReportCallbackCreateInfoEXT **infos, + VkDebugReportCallbackEXT **callbacks) { uint32_t n = *num_callbacks = 0; const void *pNext = pChain; @@ -279,22 +638,23 @@ static inline VkResult layer_copy_tmp_callbacks(const void *pChain, uint32_t *nu return VK_SUCCESS; } -// This utility frees the arrays allocated by layer_copy_tmp_callbacks() -static inline void layer_free_tmp_callbacks(VkDebugReportCallbackCreateInfoEXT *infos, VkDebugReportCallbackEXT *callbacks) { +// This utility frees the arrays allocated by layer_copy_tmp_report_callbacks() +static inline void layer_free_tmp_report_callbacks(VkDebugReportCallbackCreateInfoEXT *infos, VkDebugReportCallbackEXT *callbacks) { free(infos); free(callbacks); } // This utility enables all of the VkDebugReportCallbackCreateInfoEXT structs -// that were copied by layer_copy_tmp_callbacks() -static inline VkResult layer_enable_tmp_callbacks(debug_report_data *debug_data, uint32_t num_callbacks, - VkDebugReportCallbackCreateInfoEXT *infos, VkDebugReportCallbackEXT *callbacks) { +// that were copied by layer_copy_tmp_report_callbacks() +static inline VkResult layer_enable_tmp_report_callbacks(debug_report_data *debug_data, uint32_t num_callbacks, + VkDebugReportCallbackCreateInfoEXT *infos, + VkDebugReportCallbackEXT *callbacks) { VkResult rtn = VK_SUCCESS; for (uint32_t i = 0; i < num_callbacks; i++) { - rtn = layer_create_msg_callback(debug_data, false, &infos[i], NULL, &callbacks[i]); + rtn = layer_create_report_callback(debug_data, false, &infos[i], NULL, &callbacks[i]); if (rtn != VK_SUCCESS) { for (uint32_t j = 0; j < i; j++) { - layer_destroy_msg_callback(debug_data, callbacks[j], NULL); + layer_destroy_report_callback(debug_data, callbacks[j], NULL); } return rtn; } @@ -303,19 +663,104 @@ static inline VkResult layer_enable_tmp_callbacks(debug_report_data *debug_data, } // This utility disables all of the VkDebugReportCallbackCreateInfoEXT structs -// that were copied by layer_copy_tmp_callbacks() -static inline void layer_disable_tmp_callbacks(debug_report_data *debug_data, uint32_t num_callbacks, - VkDebugReportCallbackEXT *callbacks) { +// that were copied by layer_copy_tmp_report_callbacks() +static inline void layer_disable_tmp_report_callbacks(debug_report_data *debug_data, uint32_t num_callbacks, + VkDebugReportCallbackEXT *callbacks) { for (uint32_t i = 0; i < num_callbacks; i++) { - layer_destroy_msg_callback(debug_data, callbacks[i], NULL); + layer_destroy_report_callback(debug_data, callbacks[i], NULL); + } +} + +// This utility (called at vkCreateInstance() time), looks at a pNext chain. +// It counts any VkDebugUtilsMessengerCreateInfoEXT structs that it finds. It +// then allocates an array that can hold that many structs, as well as that +// many VkDebugUtilsMessengerEXT handles. It then copies each +// VkDebugUtilsMessengerCreateInfoEXT, and initializes each handle. +static VkResult layer_copy_tmp_debug_messengers(const void *pChain, uint32_t *num_messengers, + VkDebugUtilsMessengerCreateInfoEXT **infos, VkDebugUtilsMessengerEXT **messengers) { + uint32_t n = *num_messengers = 0; + + 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: + VkDebugUtilsMessengerCreateInfoEXT *pInfos = *infos = + ((VkDebugUtilsMessengerCreateInfoEXT *)malloc(n * sizeof(VkDebugUtilsMessengerCreateInfoEXT))); + if (!pInfos) { + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + // 3rd, allocate memory for a unique handle for each messenger: + VkDebugUtilsMessengerEXT *pMessengers = *messengers = + ((VkDebugUtilsMessengerEXT *)malloc(n * sizeof(VkDebugUtilsMessengerEXT))); + if (!pMessengers) { + free(pInfos); + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + // 4th, copy each VkDebugUtilsMessengerCreateInfoEXT for use by + // vkDestroyInstance, and assign a unique handle to each callback (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)pInfos++; + } + pNext = (void *)((VkInstanceCreateInfo *)pNext)->pNext; + } + + *num_messengers = n; + return VK_SUCCESS; +} + +// This utility frees the arrays allocated by layer_copy_tmp_debug_messengers() +static void layer_free_tmp_debug_messengers(VkDebugUtilsMessengerCreateInfoEXT *infos, VkDebugUtilsMessengerEXT *messengers) { + free(infos); + free(messengers); +} + +// This utility enables all of the VkDebugUtilsMessengerCreateInfoEXT structs +// that were copied by layer_copy_tmp_debug_messengers() +static VkResult layer_enable_tmp_debug_messengers(debug_report_data *debug_data, uint32_t num_messengers, + VkDebugUtilsMessengerCreateInfoEXT *infos, VkDebugUtilsMessengerEXT *messengers) { + VkResult rtn = VK_SUCCESS; + for (uint32_t i = 0; i < num_messengers; i++) { + rtn = layer_create_messenger_callback(debug_data, false, &infos[i], NULL, &messengers[i]); + if (rtn != VK_SUCCESS) { + for (uint32_t j = 0; j < i; j++) { + layer_destroy_messenger_callback(debug_data, messengers[j], NULL); + } + return rtn; + } + } + return rtn; +} + +// This utility disables all of the VkDebugUtilsMessengerCreateInfoEXT structs +// that were copied by layer_copy_tmp_debug_messengers() +static void layer_disable_tmp_debug_messengers(debug_report_data *debug_data, uint32_t num_messengers, + VkDebugUtilsMessengerEXT *messengers) { + for (uint32_t i = 0; i < num_messengers; i++) { + layer_destroy_messenger_callback(debug_data, messengers[i], NULL); } } // Checks if the message will get logged. // Allows layer to defer collecting & formating data if the // message will be discarded. -static inline bool will_log_msg(debug_report_data *debug_data, VkFlags msgFlags) { - if (!debug_data || !(debug_data->active_flags & msgFlags)) { +static inline bool will_log_msg(debug_report_data *debug_data, VkFlags msg_flags) { + VkFlags local_severity = 0; + VkFlags local_type = 0; + DebugReportFlagsToAnnotFlags(msg_flags, true, &local_severity, &local_type); + if (!debug_data || !(debug_data->active_severities & local_severity) || !(debug_data->active_types & local_type)) { // Message is not wanted return false; } @@ -358,14 +803,17 @@ static inline int vasprintf(char **strp, char const *fmt, va_list ap) { // Takes format and variable arg list so that output string // is only computed if a message needs to be logged #ifndef WIN32 -static inline bool log_msg(const debug_report_data *debug_data, VkFlags msgFlags, VkDebugReportObjectTypeEXT objectType, - uint64_t srcObject, size_t location, int32_t msgCode, const char *pLayerPrefix, const char *format, ...) - __attribute__((format(printf, 8, 9))); +static inline bool log_msg(const debug_report_data *debug_data, VkFlags msg_flags, VkDebugReportObjectTypeEXT object_type, + uint64_t src_object, size_t location, int32_t msg_code, const char *layer_prefix, const char *format, + ...) __attribute__((format(printf, 8, 9))); #endif -static inline bool log_msg(const debug_report_data *debug_data, VkFlags msgFlags, VkDebugReportObjectTypeEXT objectType, - uint64_t srcObject, size_t location, int32_t msgCode, const char *pLayerPrefix, const char *format, +static inline bool log_msg(const debug_report_data *debug_data, VkFlags msg_flags, VkDebugReportObjectTypeEXT object_type, + uint64_t src_object, size_t location, int32_t msg_code, const char *layer_prefix, const char *format, ...) { - if (!debug_data || !(debug_data->active_flags & msgFlags)) { + VkFlags local_severity = 0; + VkFlags local_type = 0; + DebugReportFlagsToAnnotFlags(msg_flags, true, &local_severity, &local_type); + if (!debug_data || !(debug_data->active_severities & local_severity) || !(debug_data->active_types & local_type)) { // Message is not wanted return false; } @@ -378,37 +826,38 @@ static inline bool log_msg(const debug_report_data *debug_data, VkFlags msgFlags str = nullptr; } va_end(argptr); - bool result = debug_report_log_msg(debug_data, msgFlags, objectType, srcObject, location, msgCode, pLayerPrefix, - str ? str : "Allocation failure"); + bool result = debug_log_msg(debug_data, msg_flags, object_type, src_object, location, msg_code, layer_prefix, + str ? str : "Allocation failure"); free(str); return result; } -static inline VKAPI_ATTR VkBool32 VKAPI_CALL log_callback(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject, - size_t location, int32_t msgCode, const char *pLayerPrefix, - const char *pMsg, void *pUserData) { - char msg_flags[30]; +static inline VKAPI_ATTR VkBool32 VKAPI_CALL report_log_callback(VkFlags msg_flags, VkDebugReportObjectTypeEXT obj_type, + uint64_t src_object, size_t location, int32_t msg_code, + const char *layer_prefix, const char *message, void *user_data) { + char msg_flag_string[30]; - print_msg_flags(msgFlags, msg_flags); + PrintMessageFlags(msg_flags, msg_flag_string); - fprintf((FILE *)pUserData, "%s(%s): object: 0x%" PRIx64 " type: %d location: %lu msgCode: %d: %s\n", pLayerPrefix, msg_flags, - srcObject, objType, (unsigned long)location, msgCode, pMsg); - fflush((FILE *)pUserData); + fprintf((FILE *)user_data, "%s(%s): object: 0x%" PRIx64 " type: %d location: %lu msg_code: %d: %s\n", layer_prefix, + msg_flag_string, src_object, obj_type, (unsigned long)location, msg_code, message); + fflush((FILE *)user_data); return false; } -static inline VKAPI_ATTR VkBool32 VKAPI_CALL win32_debug_output_msg(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType, - uint64_t srcObject, size_t location, int32_t msgCode, - const char *pLayerPrefix, const char *pMsg, void *pUserData) { +static inline VKAPI_ATTR VkBool32 VKAPI_CALL report_win32_debug_output_msg(VkFlags msg_flags, VkDebugReportObjectTypeEXT obj_type, + uint64_t src_object, size_t location, int32_t msg_code, + const char *layer_prefix, const char *message, + void *user_data) { #ifdef WIN32 - char msg_flags[30]; + char msg_flag_string[30]; char buf[2048]; - print_msg_flags(msgFlags, msg_flags); + PrintMessageFlags(msg_flags, msg_flag_string); _snprintf(buf, sizeof(buf) - 1, - "%s (%s): object: 0x%" PRIxPTR " type: %d location: " PRINTF_SIZE_T_SPECIFIER " msgCode: %d: %s\n", pLayerPrefix, - msg_flags, (size_t)srcObject, objType, location, msgCode, pMsg); + "%s (%s): object: 0x%" PRIxPTR " type: %d location: " PRINTF_SIZE_T_SPECIFIER " msg_code: %d: %s\n", layer_prefix, + msg_flag_string, (size_t)src_object, obj_type, location, msg_code, message); OutputDebugString(buf); #endif @@ -416,9 +865,9 @@ static inline VKAPI_ATTR VkBool32 VKAPI_CALL win32_debug_output_msg(VkFlags msgF return false; } -static inline VKAPI_ATTR VkBool32 VKAPI_CALL DebugBreakCallback(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType, - uint64_t srcObject, size_t location, int32_t msgCode, - const char *pLayerPrefix, const char *pMsg, void *pUserData) { +static inline VKAPI_ATTR VkBool32 VKAPI_CALL DebugBreakCallback(VkFlags msgFlags, VkDebugReportObjectTypeEXT obj_type, + uint64_t src_object, size_t location, int32_t msg_code, + const char *layer_prefix, const char *message, void *user_data) { #ifdef WIN32 DebugBreak(); #else @@ -428,15 +877,177 @@ static inline VKAPI_ATTR VkBool32 VKAPI_CALL DebugBreakCallback(VkFlags msgFlags return false; } -// TODO: Could be autogenerated for the specific handles for extra type safety... -template <typename HANDLE_T> -static inline uint64_t HandleToUint64(HANDLE_T *h) { - return reinterpret_cast<uint64_t>(h); +static inline VKAPI_ATTR VkBool32 VKAPI_CALL messenger_log_callback(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, + VkDebugUtilsMessageTypeFlagsEXT message_type, + const VkDebugUtilsMessengerCallbackDataEXT *callback_data, + void *user_data) { + char msg_severity[30]; + char msg_type[30]; + + PrintMessageSeverity(message_severity, msg_severity); + PrintMessageType(message_type, msg_type); + + fprintf((FILE *)user_data, "%s(%s / %s): object: 0x%" PRIx64 " type: %d msgNum: %d - %s\n", callback_data->pMessageIdName, + msg_severity, msg_type, callback_data->pObjects[0].objectHandle, callback_data->pObjects[0].objectType, + callback_data->messageIdNumber, callback_data->pMessage); + fflush((FILE *)user_data); + + return false; } -template <typename HANDLE_T> -uint64_t HandleToUint64(HANDLE_T h); +static inline VKAPI_ATTR VkBool32 VKAPI_CALL messenger_win32_debug_output_msg( + VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, VkDebugUtilsMessageTypeFlagsEXT message_type, + const VkDebugUtilsMessengerCallbackDataEXT *callback_data, void *user_data) { +#ifdef WIN32 + char buf[2048]; + char msg_severity[30]; + char msg_type[30]; -static inline uint64_t HandleToUint64(uint64_t h) { return h; } + PrintMessageSeverity(message_severity, msg_severity); + PrintMessageType(message_type, msg_type); + + _snprintf(buf, sizeof(buf) - 1, "%s (%s / %s): object: 0x%" PRIxPTR " type: %d msgNum: %d - %s\n", + callback_data->pMessageIdName, msg_severity, msg_type, callback_data->pObjects[0].objectHandle, + callback_data->pObjects[0].objectType, callback_data->messageIdNumber, callback_data->pMessage); + + OutputDebugString(buf); +#endif + + return false; +} + +// This utility converts from the VkDebugUtilsLabelEXT structure into the logging version of the structure. +// In the logging version, we only record what we absolutely need to convey back to the callbacks. +static inline void InsertLabelIntoLog(const VkDebugUtilsLabelEXT *utils_label, std::vector<LoggingLabelData> &log_vector) { + LoggingLabelData log_label_data = {}; + log_label_data.name = utils_label->pLabelName; + log_label_data.color[0] = utils_label->color[0]; + log_label_data.color[1] = utils_label->color[1]; + log_label_data.color[2] = utils_label->color[2]; + log_label_data.color[3] = utils_label->color[3]; + log_vector.push_back(log_label_data); +} + +static void BeginQueueDebugUtilsLabel(debug_report_data *report_data, VkQueue queue, const VkDebugUtilsLabelEXT *label_info) { + if (nullptr != label_info && nullptr != label_info->pLabelName) { + auto label_iter = report_data->debugUtilsQueueLabels->find(queue); + if (label_iter == report_data->debugUtilsQueueLabels->end()) { + std::vector<LoggingLabelData> new_queue_labels; + InsertLabelIntoLog(label_info, new_queue_labels); + report_data->debugUtilsQueueLabels->insert({queue, new_queue_labels}); + } else { + // If the last thing was a label insert, we need to pop it off of the label vector before any + // changes. This is because a label added with "vkQueueInsertDebugUtilsLabelEXT" is only a + // temporary location that exists until the next operation occurs. In this case, a new + // "vkQueueBeginDebugUtilsLabelEXT" has occurred erasing the previous inserted label. + if (report_data->queueLabelHasInsert) { + report_data->queueLabelHasInsert = false; + label_iter->second.pop_back(); + } + InsertLabelIntoLog(label_info, label_iter->second); + } + } +} + +static void EndQueueDebugUtilsLabel(debug_report_data *report_data, VkQueue queue) { + auto label_iter = report_data->debugUtilsQueueLabels->find(queue); + if (label_iter != report_data->debugUtilsQueueLabels->end()) { + // If the last thing was a label insert, we need to pop it off of the label vector before any + // changes. This is because a label added with "vkQueueInsertDebugUtilsLabelEXT" is only a + // temporary location that exists until the next operation occurs. In this case, a + // "vkQueueEndDebugUtilsLabelEXT" has occurred erasing the inserted label. + if (report_data->queueLabelHasInsert) { + report_data->queueLabelHasInsert = false; + label_iter->second.pop_back(); + } + // Now pop the normal item + label_iter->second.pop_back(); + } +} + +static void InsertQueueDebugUtilsLabel(debug_report_data *report_data, VkQueue queue, const VkDebugUtilsLabelEXT *label_info) { + if (nullptr != label_info && nullptr != label_info->pLabelName) { + auto label_iter = report_data->debugUtilsQueueLabels->find(queue); + if (label_iter == report_data->debugUtilsQueueLabels->end()) { + std::vector<LoggingLabelData> new_queue_labels; + InsertLabelIntoLog(label_info, new_queue_labels); + report_data->debugUtilsQueueLabels->insert({queue, new_queue_labels}); + } else { + // If the last thing was a label insert, we need to pop it off of the label vector before any + // changes. This is because a label added with "vkQueueInsertDebugUtilsLabelEXT" is only a + // temporary location that exists until the next operation occurs. In this case, a new + // "vkQueueInsertDebugUtilsLabelEXT" has occurred erasing the previous inserted label. + if (report_data->queueLabelHasInsert) { + label_iter->second.pop_back(); + } + // Insert this new label and mark it as one that has been "inserted" so we can remove it on + // the next queue label operation. + InsertLabelIntoLog(label_info, label_iter->second); + report_data->queueLabelHasInsert = true; + } + } +} + +static void BeginCmdDebugUtilsLabel(debug_report_data *report_data, VkCommandBuffer command_buffer, + const VkDebugUtilsLabelEXT *label_info) { + if (nullptr != label_info && nullptr != label_info->pLabelName) { + auto label_iter = report_data->debugUtilsCmdBufLabels->find(command_buffer); + if (label_iter == report_data->debugUtilsCmdBufLabels->end()) { + std::vector<LoggingLabelData> new_cmdbuf_labels; + InsertLabelIntoLog(label_info, new_cmdbuf_labels); + report_data->debugUtilsCmdBufLabels->insert({command_buffer, new_cmdbuf_labels}); + } else { + // If the last thing was a label insert, we need to pop it off of the label vector before any + // changes. This is because a label added with "vkCmdInsertDebugUtilsLabelEXT" is only a + // temporary location that exists until the next operation occurs. In this case, a + // "vkCmdBeginDebugUtilsLabelEXT" has occurred erasing the inserted label. + if (report_data->cmdBufLabelHasInsert) { + report_data->cmdBufLabelHasInsert = false; + label_iter->second.pop_back(); + } + InsertLabelIntoLog(label_info, label_iter->second); + } + } +} + +static void EndCmdDebugUtilsLabel(debug_report_data *report_data, VkCommandBuffer command_buffer) { + auto label_iter = report_data->debugUtilsCmdBufLabels->find(command_buffer); + if (label_iter != report_data->debugUtilsCmdBufLabels->end()) { + // If the last thing was a label insert, we need to pop it off of the label vector before any + // changes. This is because a label added with "vkCmdInsertDebugUtilsLabelEXT" is only a + // temporary location that exists until the next operation occurs. In this case, a + // "vkCmdEndDebugUtilsLabelEXT" has occurred erasing the inserted label. + if (report_data->cmdBufLabelHasInsert) { + report_data->cmdBufLabelHasInsert = false; + label_iter->second.pop_back(); + } + // Now pop the normal item + label_iter->second.pop_back(); + } +} + +static void InsertCmdDebugUtilsLabel(debug_report_data *report_data, VkCommandBuffer command_buffer, + const VkDebugUtilsLabelEXT *label_info) { + if (nullptr != label_info && nullptr != label_info->pLabelName) { + auto label_iter = report_data->debugUtilsCmdBufLabels->find(command_buffer); + if (label_iter == report_data->debugUtilsCmdBufLabels->end()) { + std::vector<LoggingLabelData> new_cmdbuf_labels; + InsertLabelIntoLog(label_info, new_cmdbuf_labels); + report_data->debugUtilsCmdBufLabels->insert({command_buffer, new_cmdbuf_labels}); + } else { + // If the last thing was a label insert, we need to pop it off of the label vector before any + // changes. This is because a label added with "vkCmdInsertDebugUtilsLabelEXT" is only a + // temporary location that exists until the next operation occurs. In this case, a new + // "vkCmdInsertDebugUtilsLabelEXT" has occurred erasing the previous inserted label. + if (report_data->cmdBufLabelHasInsert) { + label_iter->second.pop_back(); + } + // Insert this new label and mark it as one that has been "inserted" so we can remove it on + // the next command buffer label operation. + InsertLabelIntoLog(label_info, label_iter->second); + report_data->cmdBufLabelHasInsert = true; + } + } +} #endif // LAYER_LOGGING_H diff --git a/layers/vk_layer_utils.cpp b/layers/vk_layer_utils.cpp index d788daf7..629b19f4 100644 --- a/layers/vk_layer_utils.cpp +++ b/layers/vk_layer_utils.cpp @@ -91,8 +91,9 @@ VK_LAYER_EXPORT bool white_list(const char *item, const char *list) { // If a vk_layer_settings.txt file is present and an application defines a debug callback, both callbacks // will be active. If no vk_layer_settings.txt file is present, creating an application-defined debug // callback will cause the default callbacks to be unregisterd and removed. -VK_LAYER_EXPORT void layer_debug_actions(debug_report_data *report_data, std::vector<VkDebugReportCallbackEXT> &logging_callback, - const VkAllocationCallbacks *pAllocator, const char *layer_identifier) { +VK_LAYER_EXPORT void layer_debug_report_actions(debug_report_data *report_data, + std::vector<VkDebugReportCallbackEXT> &logging_callback, + const VkAllocationCallbacks *pAllocator, const char *layer_identifier) { VkDebugReportCallbackEXT callback = VK_NULL_HANDLE; std::string report_flags_key = layer_identifier; @@ -115,9 +116,9 @@ VK_LAYER_EXPORT void layer_debug_actions(debug_report_data *report_data, std::ve memset(&dbgCreateInfo, 0, sizeof(dbgCreateInfo)); dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT; dbgCreateInfo.flags = report_flags; - dbgCreateInfo.pfnCallback = log_callback; + dbgCreateInfo.pfnCallback = report_log_callback; dbgCreateInfo.pUserData = (void *)log_output; - layer_create_msg_callback(report_data, default_layer_callback, &dbgCreateInfo, pAllocator, &callback); + layer_create_report_callback(report_data, default_layer_callback, &dbgCreateInfo, pAllocator, &callback); logging_callback.push_back(callback); } @@ -128,9 +129,9 @@ VK_LAYER_EXPORT void layer_debug_actions(debug_report_data *report_data, std::ve memset(&dbgCreateInfo, 0, sizeof(dbgCreateInfo)); dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT; dbgCreateInfo.flags = report_flags; - dbgCreateInfo.pfnCallback = win32_debug_output_msg; + dbgCreateInfo.pfnCallback = report_win32_debug_output_msg; dbgCreateInfo.pUserData = NULL; - layer_create_msg_callback(report_data, default_layer_callback, &dbgCreateInfo, pAllocator, &callback); + layer_create_report_callback(report_data, default_layer_callback, &dbgCreateInfo, pAllocator, &callback); logging_callback.push_back(callback); } @@ -143,7 +144,64 @@ VK_LAYER_EXPORT void layer_debug_actions(debug_report_data *report_data, std::ve dbgCreateInfo.flags = report_flags; dbgCreateInfo.pfnCallback = DebugBreakCallback; dbgCreateInfo.pUserData = NULL; - layer_create_msg_callback(report_data, default_layer_callback, &dbgCreateInfo, pAllocator, &callback); + layer_create_report_callback(report_data, default_layer_callback, &dbgCreateInfo, pAllocator, &callback); logging_callback.push_back(callback); } } + +VK_LAYER_EXPORT void layer_debug_messenger_actions(debug_report_data *report_data, + std::vector<VkDebugUtilsMessengerEXT> &logging_messenger, + const VkAllocationCallbacks *pAllocator, const char *layer_identifier) { + VkDebugUtilsMessengerEXT messenger = VK_NULL_HANDLE; + + std::string report_flags_key = layer_identifier; + std::string debug_action_key = layer_identifier; + std::string log_filename_key = layer_identifier; + report_flags_key.append(".report_flags"); + debug_action_key.append(".debug_action"); + log_filename_key.append(".log_filename"); + + // Initialize layer options + VkDebugReportFlagsEXT report_flags = GetLayerOptionFlags(report_flags_key, report_flags_option_definitions, 0); + VkLayerDbgActionFlags debug_action = GetLayerOptionFlags(debug_action_key, debug_actions_option_definitions, 0); + // Flag as default if these settings are not from a vk_layer_settings.txt file + bool default_layer_callback = (debug_action & VK_DBG_LAYER_ACTION_DEFAULT) ? true : false; + VkDebugUtilsMessengerCreateInfoEXT dbgCreateInfo; + memset(&dbgCreateInfo, 0, sizeof(dbgCreateInfo)); + dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT; + dbgCreateInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT; + if (report_flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) { + dbgCreateInfo.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; + } + if (report_flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) { + dbgCreateInfo.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT; + } + if (report_flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) { + dbgCreateInfo.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT; + dbgCreateInfo.messageType |= VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; + } + if (report_flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) { + dbgCreateInfo.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT; + } + if (report_flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) { + dbgCreateInfo.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT; + } + + if (debug_action & VK_DBG_LAYER_ACTION_LOG_MSG) { + const char *log_filename = getLayerOption(log_filename_key.c_str()); + FILE *log_output = getLayerLogOutput(log_filename, layer_identifier); + dbgCreateInfo.pfnUserCallback = messenger_log_callback; + dbgCreateInfo.pUserData = (void *)log_output; + layer_create_messenger_callback(report_data, default_layer_callback, &dbgCreateInfo, pAllocator, &messenger); + logging_messenger.push_back(messenger); + } + + messenger = VK_NULL_HANDLE; + + if (debug_action & VK_DBG_LAYER_ACTION_DEBUG_OUTPUT) { + dbgCreateInfo.pfnUserCallback = messenger_win32_debug_output_msg; + dbgCreateInfo.pUserData = NULL; + layer_create_messenger_callback(report_data, default_layer_callback, &dbgCreateInfo, pAllocator, &messenger); + logging_messenger.push_back(messenger); + } +} diff --git a/layers/vk_layer_utils.h b/layers/vk_layer_utils.h index d1969c84..08574a5e 100644 --- a/layers/vk_layer_utils.h +++ b/layers/vk_layer_utils.h @@ -37,10 +37,6 @@ extern "C" { #define VK_LAYER_API_VERSION VK_MAKE_VERSION(1, 0, VK_HEADER_VERSION) - - - - typedef enum VkStringErrorFlagBits { VK_STRING_ERROR_NONE = 0x00000000, VK_STRING_ERROR_LENGTH = 0x00000001, @@ -48,8 +44,13 @@ typedef enum VkStringErrorFlagBits { } VkStringErrorFlagBits; typedef VkFlags VkStringErrorFlags; -VK_LAYER_EXPORT void layer_debug_actions(debug_report_data *report_data, std::vector<VkDebugReportCallbackEXT> &logging_callback, - const VkAllocationCallbacks *pAllocator, const char *layer_identifier); +VK_LAYER_EXPORT void layer_debug_report_actions(debug_report_data *report_data, + std::vector<VkDebugReportCallbackEXT> &logging_callback, + const VkAllocationCallbacks *pAllocator, const char *layer_identifier); + +VK_LAYER_EXPORT void layer_debug_messenger_actions(debug_report_data *report_data, + std::vector<VkDebugUtilsMessengerEXT> &logging_messenger, + const VkAllocationCallbacks *pAllocator, const char *layer_identifier); VK_LAYER_EXPORT VkStringErrorFlags vk_string_validate(const int max_length, const char *char_array); VK_LAYER_EXPORT bool white_list(const char *item, const char *whitelist); |
