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 | |
| 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
32 files changed, 2917 insertions, 930 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); diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt index 2f96665a..f543f861 100644 --- a/loader/CMakeLists.txt +++ b/loader/CMakeLists.txt @@ -75,8 +75,8 @@ set(NORMAL_LOADER_SRCS trampoline.c wsi.c wsi.h - debug_report.c - debug_report.h + debug_utils.c + debug_utils.h gpa_helper.h cJSON.c cJSON.h diff --git a/loader/debug_report.c b/loader/debug_report.c deleted file mode 100644 index 04e55ccf..00000000 --- a/loader/debug_report.c +++ /dev/null @@ -1,466 +0,0 @@ -/* - * Copyright (c) 2015-2016 The Khronos Group Inc. - * Copyright (c) 2015-2016 Valve Corporation - * Copyright (c) 2015-2016 LunarG, Inc. - * Copyright (C) 2015-2016 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Author: Courtney Goeltzenleuchter <courtney@LunarG.com> - * Author: Jon Ashburn <jon@LunarG.com> - * - */ - -#define _GNU_SOURCE -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <inttypes.h> -#ifndef WIN32 -#include <signal.h> -#else -#endif -#include "vk_loader_platform.h" -#include "debug_report.h" -#include "vulkan/vk_layer.h" - -typedef void(VKAPI_PTR *PFN_stringCallback)(char *message); - -static const VkExtensionProperties debug_report_extension_info = { - .extensionName = VK_EXT_DEBUG_REPORT_EXTENSION_NAME, .specVersion = VK_EXT_DEBUG_REPORT_SPEC_VERSION, -}; - -void debug_report_add_instance_extensions(const struct loader_instance *inst, struct loader_extension_list *ext_list) { - loader_add_to_ext_list(inst, ext_list, 1, &debug_report_extension_info); -} - -void debug_report_create_instance(struct loader_instance *ptr_instance, const VkInstanceCreateInfo *pCreateInfo) { - ptr_instance->enabled_known_extensions.ext_debug_report = 0; - - for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) { - if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0) { - ptr_instance->enabled_known_extensions.ext_debug_report = 1; - return; - } - } -} - -VkResult util_CreateDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackCreateInfoEXT *pCreateInfo, - const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT callback) { - VkLayerDbgFunctionNode *pNewDbgFuncNode = NULL; - -#if (DEBUG_DISABLE_APP_ALLOCATORS == 1) - { -#else - if (pAllocator != NULL) { - pNewDbgFuncNode = (VkLayerDbgFunctionNode *)pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(VkLayerDbgFunctionNode), - sizeof(int *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); - } else { -#endif - pNewDbgFuncNode = (VkLayerDbgFunctionNode *)loader_instance_heap_alloc(inst, sizeof(VkLayerDbgFunctionNode), - VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); - } - if (!pNewDbgFuncNode) { - return VK_ERROR_OUT_OF_HOST_MEMORY; - } - memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode)); - - pNewDbgFuncNode->msgCallback = callback; - pNewDbgFuncNode->pfnMsgCallback = pCreateInfo->pfnCallback; - pNewDbgFuncNode->msgFlags = pCreateInfo->flags; - pNewDbgFuncNode->pUserData = pCreateInfo->pUserData; - pNewDbgFuncNode->pNext = inst->DbgFunctionHead; - inst->DbgFunctionHead = pNewDbgFuncNode; - - return VK_SUCCESS; -} - -static VKAPI_ATTR VkResult VKAPI_CALL -debug_report_CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo, - const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pCallback) { - struct loader_instance *inst = loader_get_instance(instance); - loader_platform_thread_lock_mutex(&loader_lock); - VkResult result = inst->disp->layer_inst_disp.CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback); - loader_platform_thread_unlock_mutex(&loader_lock); - return result; -} - -// Utility function to handle reporting -VkBool32 util_DebugReportMessage(const struct loader_instance *inst, VkFlags msgFlags, VkDebugReportObjectTypeEXT objectType, - uint64_t srcObject, size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) { - VkBool32 bail = false; - VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead; - while (pTrav) { - if (pTrav->msgFlags & msgFlags) { - if (pTrav->pfnMsgCallback(msgFlags, objectType, srcObject, location, msgCode, pLayerPrefix, pMsg, pTrav->pUserData)) { - bail = true; - } - } - pTrav = pTrav->pNext; - } - - return bail; -} - -void util_DestroyDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackEXT callback, - const VkAllocationCallbacks *pAllocator) { - VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead; - VkLayerDbgFunctionNode *pPrev = pTrav; - - while (pTrav) { - if (pTrav->msgCallback == callback) { - pPrev->pNext = pTrav->pNext; - if (inst->DbgFunctionHead == pTrav) inst->DbgFunctionHead = pTrav->pNext; -#if (DEBUG_DISABLE_APP_ALLOCATORS == 1) - { -#else - if (pAllocator != NULL) { - pAllocator->pfnFree(pAllocator->pUserData, pTrav); - } else { -#endif - loader_instance_heap_free(inst, pTrav); - } - break; - } - pPrev = pTrav; - pTrav = pTrav->pNext; - } -} - -// This utility (used by vkInstanceCreateInfo(), looks at a pNext chain. It -// counts any VkDebugReportCallbackCreateInfoEXT structs that it finds. It -// then allocates array that can hold that many structs, as well as that many -// VkDebugReportCallbackEXT handles. It then copies each -// VkDebugReportCallbackCreateInfoEXT, and initializes each handle. -VkResult util_CopyDebugReportCreateInfos(const void *pChain, const VkAllocationCallbacks *pAllocator, uint32_t *num_callbacks, - VkDebugReportCallbackCreateInfoEXT **infos, VkDebugReportCallbackEXT **callbacks) { - uint32_t n = *num_callbacks = 0; - VkDebugReportCallbackCreateInfoEXT *pInfos = NULL; - VkDebugReportCallbackEXT *pCallbacks = NULL; - - // NOTE: The loader is not using pAllocator, and so this function doesn't - // either. - - const void *pNext = pChain; - while (pNext) { - // 1st, count the number VkDebugReportCallbackCreateInfoEXT: - if (((VkDebugReportCallbackCreateInfoEXT *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) { - n++; - } - pNext = (void *)((VkDebugReportCallbackCreateInfoEXT *)pNext)->pNext; - } - if (n == 0) { - return VK_SUCCESS; - } - -// 2nd, allocate memory for each VkDebugReportCallbackCreateInfoEXT: -#if (DEBUG_DISABLE_APP_ALLOCATORS == 1) - { -#else - if (pAllocator != NULL) { - pInfos = *infos = ((VkDebugReportCallbackCreateInfoEXT *)pAllocator->pfnAllocation( - pAllocator->pUserData, n * sizeof(VkDebugReportCallbackCreateInfoEXT), sizeof(void *), - VK_SYSTEM_ALLOCATION_SCOPE_OBJECT)); - } else { -#endif - pInfos = *infos = ((VkDebugReportCallbackCreateInfoEXT *)malloc(n * sizeof(VkDebugReportCallbackCreateInfoEXT))); - } - if (!pInfos) { - return VK_ERROR_OUT_OF_HOST_MEMORY; - } -// 3rd, allocate memory for a unique handle for each callback: -#if (DEBUG_DISABLE_APP_ALLOCATORS == 1) - { -#else - if (pAllocator != NULL) { - pCallbacks = *callbacks = ((VkDebugReportCallbackEXT *)pAllocator->pfnAllocation( - pAllocator->pUserData, n * sizeof(VkDebugReportCallbackEXT), sizeof(void *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT)); - if (!pCallbacks) { - pAllocator->pfnFree(pAllocator->pUserData, pInfos); - return VK_ERROR_OUT_OF_HOST_MEMORY; - } - } else { -#endif - pCallbacks = *callbacks = ((VkDebugReportCallbackEXT *)malloc(n * sizeof(VkDebugReportCallbackEXT))); - if (!pCallbacks) { - free(pInfos); - return VK_ERROR_OUT_OF_HOST_MEMORY; - } - } - // 4th, copy each VkDebugReportCallbackCreateInfoEXT for use by - // vkDestroyInstance, and assign a unique handle to each callback (just - // use the address of the copied VkDebugReportCallbackCreateInfoEXT): - pNext = pChain; - while (pNext) { - if (((VkInstanceCreateInfo *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) { - memcpy(pInfos, pNext, sizeof(VkDebugReportCallbackCreateInfoEXT)); - *pCallbacks++ = (VkDebugReportCallbackEXT)(uintptr_t)pInfos++; - } - pNext = (void *)((VkInstanceCreateInfo *)pNext)->pNext; - } - - *num_callbacks = n; - return VK_SUCCESS; -} - -void util_FreeDebugReportCreateInfos(const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackCreateInfoEXT *infos, - VkDebugReportCallbackEXT *callbacks) { -#if (DEBUG_DISABLE_APP_ALLOCATORS == 1) - { -#else - if (pAllocator != NULL) { - pAllocator->pfnFree(pAllocator->pUserData, infos); - pAllocator->pfnFree(pAllocator->pUserData, callbacks); - } else { -#endif - free(infos); - free(callbacks); - } -} - -VkResult util_CreateDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator, - uint32_t num_callbacks, VkDebugReportCallbackCreateInfoEXT *infos, - VkDebugReportCallbackEXT *callbacks) { - VkResult rtn = VK_SUCCESS; - for (uint32_t i = 0; i < num_callbacks; i++) { - rtn = util_CreateDebugReportCallback(inst, &infos[i], pAllocator, callbacks[i]); - if (rtn != VK_SUCCESS) { - for (uint32_t j = 0; j < i; j++) { - util_DestroyDebugReportCallback(inst, callbacks[j], pAllocator); - } - return rtn; - } - } - return rtn; -} - -void util_DestroyDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator, uint32_t num_callbacks, - VkDebugReportCallbackEXT *callbacks) { - for (uint32_t i = 0; i < num_callbacks; i++) { - util_DestroyDebugReportCallback(inst, callbacks[i], pAllocator); - } -} - -static VKAPI_ATTR void VKAPI_CALL debug_report_DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback, - const VkAllocationCallbacks *pAllocator) { - struct loader_instance *inst = loader_get_instance(instance); - loader_platform_thread_lock_mutex(&loader_lock); - - inst->disp->layer_inst_disp.DestroyDebugReportCallbackEXT(instance, callback, pAllocator); - - util_DestroyDebugReportCallback(inst, callback, pAllocator); - - loader_platform_thread_unlock_mutex(&loader_lock); -} - -static VKAPI_ATTR void VKAPI_CALL debug_report_DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, - VkDebugReportObjectTypeEXT objType, uint64_t object, - size_t location, int32_t msgCode, const char *pLayerPrefix, - const char *pMsg) { - struct loader_instance *inst = loader_get_instance(instance); - - inst->disp->layer_inst_disp.DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg); -} - -// This is the instance chain terminator function -// for CreateDebugReportCallback -VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugReportCallbackEXT(VkInstance instance, - const VkDebugReportCallbackCreateInfoEXT *pCreateInfo, - const VkAllocationCallbacks *pAllocator, - VkDebugReportCallbackEXT *pCallback) { - VkDebugReportCallbackEXT *icd_info = NULL; - const struct loader_icd_term *icd_term; - struct loader_instance *inst = (struct loader_instance *)instance; - VkResult res = VK_SUCCESS; - uint32_t storage_idx; - VkLayerDbgFunctionNode *pNewDbgFuncNode = NULL; - -#if (DEBUG_DISABLE_APP_ALLOCATORS == 1) - { -#else - if (pAllocator != NULL) { - icd_info = ((VkDebugReportCallbackEXT *)pAllocator->pfnAllocation(pAllocator->pUserData, - inst->total_icd_count * sizeof(VkDebugReportCallbackEXT), - sizeof(void *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT)); - if (icd_info) { - memset(icd_info, 0, inst->total_icd_count * sizeof(VkDebugReportCallbackEXT)); - } - } else { -#endif - icd_info = calloc(sizeof(VkDebugReportCallbackEXT), inst->total_icd_count); - } - if (!icd_info) { - res = VK_ERROR_OUT_OF_HOST_MEMORY; - goto out; - } - - storage_idx = 0; - for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) { - if (!icd_term->dispatch.CreateDebugReportCallbackEXT) { - continue; - } - - res = icd_term->dispatch.CreateDebugReportCallbackEXT(icd_term->instance, pCreateInfo, pAllocator, &icd_info[storage_idx]); - - if (res != VK_SUCCESS) { - goto out; - } - storage_idx++; - } - -// Setup the debug report callback in the terminator since a layer may want -// to grab the information itself (RenderDoc) and then return back to the -// user callback a sub-set of the messages. -#if (DEBUG_DISABLE_APP_ALLOCATORS == 0) - if (pAllocator != NULL) { - pNewDbgFuncNode = (VkLayerDbgFunctionNode *)pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(VkLayerDbgFunctionNode), - sizeof(int *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); - } else { -#else - { -#endif - pNewDbgFuncNode = (VkLayerDbgFunctionNode *)loader_instance_heap_alloc(inst, sizeof(VkLayerDbgFunctionNode), - VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); - } - if (!pNewDbgFuncNode) { - res = VK_ERROR_OUT_OF_HOST_MEMORY; - goto out; - } - memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode)); - - pNewDbgFuncNode->pfnMsgCallback = pCreateInfo->pfnCallback; - pNewDbgFuncNode->msgFlags = pCreateInfo->flags; - pNewDbgFuncNode->pUserData = pCreateInfo->pUserData; - pNewDbgFuncNode->pNext = inst->DbgFunctionHead; - inst->DbgFunctionHead = pNewDbgFuncNode; - - *(VkDebugReportCallbackEXT **)pCallback = icd_info; - pNewDbgFuncNode->msgCallback = *pCallback; - -out: - - // Roll back on errors - if (VK_SUCCESS != res) { - storage_idx = 0; - for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) { - if (NULL == icd_term->dispatch.DestroyDebugReportCallbackEXT) { - continue; - } - - if (icd_info && icd_info[storage_idx]) { - icd_term->dispatch.DestroyDebugReportCallbackEXT(icd_term->instance, icd_info[storage_idx], pAllocator); - } - storage_idx++; - } - -#if (DEBUG_DISABLE_APP_ALLOCATORS == 1) - { -#else - if (pAllocator != NULL) { - if (NULL != pNewDbgFuncNode) { - pAllocator->pfnFree(pAllocator->pUserData, pNewDbgFuncNode); - } - if (NULL != icd_info) { - pAllocator->pfnFree(pAllocator->pUserData, icd_info); - } - } else { -#endif - if (NULL != pNewDbgFuncNode) { - free(pNewDbgFuncNode); - } - if (NULL != icd_info) { - free(icd_info); - } - } - } - - return res; -} - -// This is the instance chain terminator function for DestroyDebugReportCallback -VKAPI_ATTR void VKAPI_CALL terminator_DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback, - const VkAllocationCallbacks *pAllocator) { - uint32_t storage_idx; - VkDebugReportCallbackEXT *icd_info; - const struct loader_icd_term *icd_term; - - struct loader_instance *inst = (struct loader_instance *)instance; - icd_info = *(VkDebugReportCallbackEXT **)&callback; - storage_idx = 0; - for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) { - if (NULL == icd_term->dispatch.DestroyDebugReportCallbackEXT) { - continue; - } - - if (icd_info[storage_idx]) { - icd_term->dispatch.DestroyDebugReportCallbackEXT(icd_term->instance, icd_info[storage_idx], pAllocator); - } - storage_idx++; - } - -#if (DEBUG_DISABLE_APP_ALLOCATORS == 1) - { -#else - if (pAllocator != NULL) { - pAllocator->pfnFree(pAllocator->pUserData, icd_info); - } else { -#endif - free(icd_info); - } -} - -// This is the instance chain terminator function for DebugReportMessage -VKAPI_ATTR void VKAPI_CALL terminator_DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, - VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location, - int32_t msgCode, const char *pLayerPrefix, const char *pMsg) { - const struct loader_icd_term *icd_term; - - struct loader_instance *inst = (struct loader_instance *)instance; - - loader_platform_thread_lock_mutex(&loader_lock); - for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) { - if (icd_term->dispatch.DebugReportMessageEXT != NULL) { - icd_term->dispatch.DebugReportMessageEXT(icd_term->instance, flags, objType, object, location, msgCode, pLayerPrefix, - pMsg); - } - } - - // Now that all ICDs have seen the message, call the necessary callbacks. Ignoring "bail" return value - // as there is nothing to bail from at this point. - - util_DebugReportMessage(inst, flags, objType, object, location, msgCode, pLayerPrefix, pMsg); - - loader_platform_thread_unlock_mutex(&loader_lock); -} - -bool debug_report_instance_gpa(struct loader_instance *ptr_instance, const char *name, void **addr) { - // debug_report is currently advertised to be supported by the loader, - // so always return the entry points if name matches and it's enabled - *addr = NULL; - - if (!strcmp("vkCreateDebugReportCallbackEXT", name)) { - *addr = (ptr_instance->enabled_known_extensions.ext_debug_report == 1) ? (void *)debug_report_CreateDebugReportCallbackEXT - : NULL; - return true; - } - if (!strcmp("vkDestroyDebugReportCallbackEXT", name)) { - *addr = (ptr_instance->enabled_known_extensions.ext_debug_report == 1) ? (void *)debug_report_DestroyDebugReportCallbackEXT - : NULL; - return true; - } - if (!strcmp("vkDebugReportMessageEXT", name)) { - *addr = (ptr_instance->enabled_known_extensions.ext_debug_report == 1) ? (void *)debug_report_DebugReportMessageEXT : NULL; - return true; - } - return false; -} diff --git a/loader/debug_report.h b/loader/debug_report.h deleted file mode 100644 index 89074d7f..00000000 --- a/loader/debug_report.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2015-2016 The Khronos Group Inc. - * Copyright (c) 2015-2016 Valve Corporation - * Copyright (c) 2015-2016 LunarG, Inc. - * Copyright (C) 2015-2016 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Author: Courtney Goeltzenleuchter <courtney@LunarG.com> - * Author: Jon Ashburn <jon@lunarg.com> - * - */ - -#include "vk_loader_platform.h" -#include "loader.h" - -// CreateMsgCallback is global and needs to be -// applied to all layers and ICDs. -// What happens if a layer is enabled on both the instance chain -// as well as the device chain and a call to CreateMsgCallback is made? -// Do we need to make sure that each layer / driver only gets called once? -// Should a layer implementing support for CreateMsgCallback only be allowed (?) -// to live on one chain? Or maybe make it the application's responsibility. -// If the app enables DRAW_STATE on at both CreateInstance time and CreateDevice -// time, CreateMsgCallback will call the DRAW_STATE layer twice. Once via -// the instance chain and once via the device chain. -// The loader should only return the DEBUG_REPORT extension as supported -// for the GetGlobalExtensionSupport call. That should help eliminate one -// duplication. -// Since the instance chain requires us iterating over the available ICDs -// and each ICD will have it's own unique MsgCallback object we need to -// track those objects to give back the right one. -// This also implies that the loader has to intercept vkDestroyObject and -// if the extension is enabled and the object type is a MsgCallback then -// we must translate the object into the proper ICD specific ones. -// DestroyObject works on a device chain. Should not be what's destroying -// the MsgCallback object. That needs to be an instance thing. So, since -// we used an instance to create it, we need a custom Destroy that also -// takes an instance. That way we can iterate over the ICDs properly. -// Example use: -// CreateInstance: DEBUG_REPORT -// Loader will create instance chain with enabled extensions. -// TODO: Should validation layers be enabled here? If not, they will not be in -// the instance chain. -// fn = GetProcAddr(INSTANCE, "vkCreateMsgCallback") -> point to loader's -// vkCreateMsgCallback -// App creates a callback object: fn(..., &MsgCallbackObject1) -// Have only established the instance chain so far. Loader will call the -// instance chain. -// Each layer in the instance chain will call down to the next layer, -// terminating with -// the CreateMsgCallback loader terminator function that creates the actual -// MsgCallbackObject1 object. -// The loader CreateMsgCallback terminator will iterate over the ICDs. -// Calling each ICD that supports vkCreateMsgCallback and collect answers in -// icd_msg_callback_map here. -// As result is sent back up the chain each layer has opportunity to record the -// callback operation and -// appropriate MsgCallback object. -// ... -// Any reports matching the flags set in MsgCallbackObject1 will generate the -// defined callback behavior -// in the layer / ICD that initiated that report. -// ... -// CreateDevice: MemTracker:... -// App does not include DEBUG_REPORT as that is a global extension. -// TODO: GetExtensionSupport must not report DEBUG_REPORT when using instance. -// App MUST include any desired validation layers or they will not participate -// in the device call chain. -// App creates a callback object: fn(..., &MsgCallbackObject2) -// Loader's vkCreateMsgCallback is called. -// Loader sends call down instance chain - this is a global extension - any -// validation layer that was -// enabled at CreateInstance will be able to register the callback. Loader will -// iterate over the ICDs and -// will record the ICD's version of the MsgCallback2 object here. -// ... -// Any report will go to the layer's report function and it will check the flags -// for MsgCallbackObject1 -// and MsgCallbackObject2 and take the appropriate action as indicated by the -// app. -// ... -// App calls vkDestroyMsgCallback( MsgCallbackObject1 ) -// Loader's DestroyMsgCallback is where call starts. DestroyMsgCallback will be -// sent down instance chain -// ending in the loader's DestroyMsgCallback terminator which will iterate over -// the ICD's destroying each -// ICD version of that MsgCallback object and then destroy the loader's version -// of the object. -// Any reports generated after this will only have MsgCallbackObject2 available. - -void debug_report_add_instance_extensions(const struct loader_instance *inst, struct loader_extension_list *ext_list); - -void debug_report_create_instance(struct loader_instance *ptr_instance, const VkInstanceCreateInfo *pCreateInfo); - -bool debug_report_instance_gpa(struct loader_instance *ptr_instance, const char *name, void **addr); - -VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugReportCallbackEXT(VkInstance instance, - const VkDebugReportCallbackCreateInfoEXT *pCreateInfo, - const VkAllocationCallbacks *pAllocator, - VkDebugReportCallbackEXT *pCallback); - -VKAPI_ATTR void VKAPI_CALL terminator_DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback, - const VkAllocationCallbacks *pAllocator); - -VKAPI_ATTR void VKAPI_CALL terminator_DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, - VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location, - int32_t msgCode, const char *pLayerPrefix, const char *pMsg); - -VkResult util_CreateDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackCreateInfoEXT *pCreateInfo, - const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT callback); - -void util_DestroyDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackEXT callback, - const VkAllocationCallbacks *pAllocator); - -VkResult util_CopyDebugReportCreateInfos(const void *pChain, const VkAllocationCallbacks *pAllocator, uint32_t *num_callbacks, - VkDebugReportCallbackCreateInfoEXT **infos, VkDebugReportCallbackEXT **callbacks); -void util_FreeDebugReportCreateInfos(const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackCreateInfoEXT *infos, - VkDebugReportCallbackEXT *callbacks); -VkResult util_CreateDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator, - uint32_t num_callbacks, VkDebugReportCallbackCreateInfoEXT *infos, - VkDebugReportCallbackEXT *callbacks); - -void util_DestroyDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator, uint32_t num_callbacks, - VkDebugReportCallbackEXT *callbacks); - -VkBool32 util_DebugReportMessage(const struct loader_instance *inst, VkFlags msgFlags, VkDebugReportObjectTypeEXT objectType, - uint64_t srcObject, size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg); diff --git a/loader/debug_utils.c b/loader/debug_utils.c new file mode 100644 index 00000000..36891319 --- /dev/null +++ b/loader/debug_utils.c @@ -0,0 +1,1004 @@ +/* + * Copyright (c) 2015-2017 The Khronos Group Inc. + * Copyright (c) 2015-2017 Valve Corporation + * Copyright (c) 2015-2017 LunarG, Inc. + * Copyright (C) 2015-2016 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Author: Courtney Goeltzenleuchter <courtney@LunarG.com> + * Author: Jon Ashburn <jon@LunarG.com> + * Author: Mark Young <marky@lunarg.com> + * + */ + +#define _GNU_SOURCE +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <inttypes.h> +#ifndef WIN32 +#include <signal.h> +#else +#endif +#include "vk_loader_platform.h" +#include "debug_utils.h" +#include "vulkan/vk_layer.h" +#include "vk_object_types.h" + +// VK_EXT_debug_report related items + +VkResult util_CreateDebugUtilsMessenger(struct loader_instance *inst, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo, + const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerEXT messenger) { + VkLayerDbgFunctionNode *pNewDbgFuncNode = NULL; + +#if (DEBUG_DISABLE_APP_ALLOCATORS == 1) + { +#else + if (pAllocator != NULL) { + pNewDbgFuncNode = (VkLayerDbgFunctionNode *)pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(VkLayerDbgFunctionNode), + sizeof(int *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + } else { +#endif + pNewDbgFuncNode = (VkLayerDbgFunctionNode *)loader_instance_heap_alloc(inst, sizeof(VkLayerDbgFunctionNode), + VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + } + if (!pNewDbgFuncNode) { + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode)); + + pNewDbgFuncNode->is_messenger = true; + pNewDbgFuncNode->messenger.messenger = messenger; + pNewDbgFuncNode->messenger.pfnUserCallback = pCreateInfo->pfnUserCallback; + pNewDbgFuncNode->messenger.messageSeverity = pCreateInfo->messageSeverity; + pNewDbgFuncNode->messenger.messageType = pCreateInfo->messageType; + pNewDbgFuncNode->pUserData = pCreateInfo->pUserData; + pNewDbgFuncNode->pNext = inst->DbgFunctionHead; + inst->DbgFunctionHead = pNewDbgFuncNode; + + return VK_SUCCESS; +} + +static VKAPI_ATTR VkResult VKAPI_CALL +debug_utils_CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo, + const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerEXT *pMessenger) { + struct loader_instance *inst = loader_get_instance(instance); + loader_platform_thread_lock_mutex(&loader_lock); + VkResult result = inst->disp->layer_inst_disp.CreateDebugUtilsMessengerEXT(instance, pCreateInfo, pAllocator, pMessenger); + loader_platform_thread_unlock_mutex(&loader_lock); + return result; +} + +VkBool32 util_SubmitDebugUtilsMessageEXT(const struct loader_instance *inst, VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageTypes, + const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData) { + VkBool32 bail = false; + + if (NULL != pCallbackData && NULL != pCallbackData->pObjects && 0 < pCallbackData->objectCount) { + VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead; + VkDebugReportObjectTypeEXT object_type; + VkDebugReportFlagsEXT object_flags = 0; + uint64_t object_handle; + + debug_utils_AnnotFlagsToReportFlags(messageSeverity, messageTypes, &object_flags); + debug_utils_AnnotObjectToDebugReportObject(pCallbackData->pObjects, &object_type, &object_handle); + + while (pTrav) { + if (pTrav->is_messenger && (pTrav->messenger.messageSeverity & messageSeverity) && + (pTrav->messenger.messageType & messageTypes)) { + if (pTrav->messenger.pfnUserCallback(messageSeverity, messageTypes, pCallbackData, pTrav->pUserData)) { + bail = true; + } + } + if (!pTrav->is_messenger && pTrav->report.msgFlags & object_flags) { + if (pTrav->report.pfnMsgCallback(object_flags, object_type, object_handle, 0, pCallbackData->messageIdNumber, + pCallbackData->pMessageIdName, pCallbackData->pMessage, pTrav->pUserData)) { + bail = true; + } + } + + pTrav = pTrav->pNext; + } + } + + return bail; +} + +void util_DestroyDebugUtilsMessenger(struct loader_instance *inst, VkDebugUtilsMessengerEXT messenger, + const VkAllocationCallbacks *pAllocator) { + VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead; + VkLayerDbgFunctionNode *pPrev = pTrav; + + while (pTrav) { + if (pTrav->is_messenger && pTrav->messenger.messenger == messenger) { + pPrev->pNext = pTrav->pNext; + if (inst->DbgFunctionHead == pTrav) inst->DbgFunctionHead = pTrav->pNext; +#if (DEBUG_DISABLE_APP_ALLOCATORS == 1) + { +#else + if (pAllocator != NULL) { + pAllocator->pfnFree(pAllocator->pUserData, pTrav); + } else { +#endif + loader_instance_heap_free(inst, pTrav); + } + break; + } + pPrev = pTrav; + pTrav = pTrav->pNext; + } +} + +// This utility (used by vkInstanceCreateInfo(), looks at a pNext chain. It +// counts any VkDebugUtilsMessengerCreateInfoEXT structs that it finds. It +// then allocates array that can hold that many structs, as well as that many +// VkDebugUtilsMessengerEXT handles. It then copies each +// VkDebugUtilsMessengerCreateInfoEXT, and initializes each handle. +VkResult util_CopyDebugUtilsMessengerCreateInfos(const void *pChain, const VkAllocationCallbacks *pAllocator, + uint32_t *num_messengers, VkDebugUtilsMessengerCreateInfoEXT **infos, + VkDebugUtilsMessengerEXT **messengers) { + uint32_t n = *num_messengers = 0; + VkDebugUtilsMessengerCreateInfoEXT *pInfos = NULL; + VkDebugUtilsMessengerEXT *pMessengers = NULL; + + 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: +#if (DEBUG_DISABLE_APP_ALLOCATORS == 1) + { +#else + if (pAllocator != NULL) { + pInfos = *infos = ((VkDebugUtilsMessengerCreateInfoEXT *)pAllocator->pfnAllocation( + pAllocator->pUserData, n * sizeof(VkDebugUtilsMessengerCreateInfoEXT), sizeof(void *), + VK_SYSTEM_ALLOCATION_SCOPE_OBJECT)); + } else { +#endif + 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 callback: +#if (DEBUG_DISABLE_APP_ALLOCATORS == 1) + { +#else + if (pAllocator != NULL) { + pMessengers = *messengers = ((VkDebugUtilsMessengerEXT *)pAllocator->pfnAllocation( + pAllocator->pUserData, n * sizeof(VkDebugUtilsMessengerEXT), sizeof(void *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT)); + if (NULL == pMessengers) { + pAllocator->pfnFree(pAllocator->pUserData, pInfos); + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + } else { +#endif + pMessengers = *messengers = ((VkDebugUtilsMessengerEXT *)malloc(n * sizeof(VkDebugUtilsMessengerEXT))); + if (NULL == 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 messenger (just + // use the address of the copied VkDebugUtilsMessengerCreateInfoEXT): + pNext = pChain; + while (pNext) { + if (((VkInstanceCreateInfo *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) { + memcpy(pInfos, pNext, sizeof(VkDebugUtilsMessengerCreateInfoEXT)); + *pMessengers++ = (VkDebugUtilsMessengerEXT)(uintptr_t)pInfos++; + } + pNext = (void *)((VkInstanceCreateInfo *)pNext)->pNext; + } + + *num_messengers = n; + return VK_SUCCESS; +} + +void util_FreeDebugUtilsMessengerCreateInfos(const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerCreateInfoEXT *infos, + VkDebugUtilsMessengerEXT *messengers) { +#if (DEBUG_DISABLE_APP_ALLOCATORS == 1) + { +#else + if (pAllocator != NULL) { + pAllocator->pfnFree(pAllocator->pUserData, infos); + pAllocator->pfnFree(pAllocator->pUserData, messengers); + } else { +#endif + free(infos); + free(messengers); + } +} + +VkResult util_CreateDebugUtilsMessengers(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator, + uint32_t num_messengers, VkDebugUtilsMessengerCreateInfoEXT *infos, + VkDebugUtilsMessengerEXT *messengers) { + VkResult rtn = VK_SUCCESS; + for (uint32_t i = 0; i < num_messengers; i++) { + rtn = util_CreateDebugUtilsMessenger(inst, &infos[i], pAllocator, messengers[i]); + if (rtn != VK_SUCCESS) { + for (uint32_t j = 0; j < i; j++) { + util_DestroyDebugUtilsMessenger(inst, messengers[j], pAllocator); + } + return rtn; + } + } + return rtn; +} + +void util_DestroyDebugUtilsMessengers(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator, + uint32_t num_messengers, VkDebugUtilsMessengerEXT *messengers) { + for (uint32_t i = 0; i < num_messengers; i++) { + util_DestroyDebugUtilsMessenger(inst, messengers[i], pAllocator); + } +} + +static VKAPI_ATTR void VKAPI_CALL debug_utils_SubmitDebugUtilsMessageEXT( + VkInstance instance, VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageTypes, + const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData) { + struct loader_instance *inst = loader_get_instance(instance); + + inst->disp->layer_inst_disp.SubmitDebugUtilsMessageEXT(instance, messageSeverity, messageTypes, pCallbackData); +} + +static VKAPI_ATTR void VKAPI_CALL debug_utils_DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger, + const VkAllocationCallbacks *pAllocator) { + struct loader_instance *inst = loader_get_instance(instance); + loader_platform_thread_lock_mutex(&loader_lock); + + inst->disp->layer_inst_disp.DestroyDebugUtilsMessengerEXT(instance, messenger, pAllocator); + + util_DestroyDebugUtilsMessenger(inst, messenger, pAllocator); + + loader_platform_thread_unlock_mutex(&loader_lock); +} + +// This is the instance chain terminator function for CreateDebugUtilsMessenger +VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugUtilsMessengerEXT(VkInstance instance, + const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo, + const VkAllocationCallbacks *pAllocator, + VkDebugUtilsMessengerEXT *pMessenger) { + VkDebugUtilsMessengerEXT *icd_info = NULL; + const struct loader_icd_term *icd_term; + struct loader_instance *inst = (struct loader_instance *)instance; + VkResult res = VK_SUCCESS; + uint32_t storage_idx; + VkLayerDbgFunctionNode *pNewDbgFuncNode = NULL; + +#if (DEBUG_DISABLE_APP_ALLOCATORS == 1) + { +#else + if (pAllocator != NULL) { + icd_info = ((VkDebugUtilsMessengerEXT *)pAllocator->pfnAllocation(pAllocator->pUserData, + inst->total_icd_count * sizeof(VkDebugUtilsMessengerEXT), + sizeof(void *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT)); + if (icd_info) { + memset(icd_info, 0, inst->total_icd_count * sizeof(VkDebugUtilsMessengerEXT)); + } + } else { +#endif + icd_info = calloc(sizeof(VkDebugUtilsMessengerEXT), inst->total_icd_count); + } + if (!icd_info) { + res = VK_ERROR_OUT_OF_HOST_MEMORY; + goto out; + } + + storage_idx = 0; + for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) { + if (!icd_term->dispatch.CreateDebugUtilsMessengerEXT) { + continue; + } + + res = icd_term->dispatch.CreateDebugUtilsMessengerEXT(icd_term->instance, pCreateInfo, pAllocator, &icd_info[storage_idx]); + + if (res != VK_SUCCESS) { + goto out; + } + storage_idx++; + } + +// Setup the debug report callback in the terminator since a layer may want +// to grab the information itself (RenderDoc) and then return back to the +// user callback a sub-set of the messages. +#if (DEBUG_DISABLE_APP_ALLOCATORS == 0) + if (pAllocator != NULL) { + pNewDbgFuncNode = (VkLayerDbgFunctionNode *)pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(VkLayerDbgFunctionNode), + sizeof(int *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + } else { +#else + { +#endif + pNewDbgFuncNode = (VkLayerDbgFunctionNode *)loader_instance_heap_alloc(inst, sizeof(VkLayerDbgFunctionNode), + VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + } + if (!pNewDbgFuncNode) { + res = VK_ERROR_OUT_OF_HOST_MEMORY; + goto out; + } + memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode)); + + pNewDbgFuncNode->is_messenger = true; + pNewDbgFuncNode->messenger.pfnUserCallback = pCreateInfo->pfnUserCallback; + pNewDbgFuncNode->messenger.messageSeverity = pCreateInfo->messageSeverity; + pNewDbgFuncNode->messenger.messageType = pCreateInfo->messageType; + pNewDbgFuncNode->pUserData = pCreateInfo->pUserData; + pNewDbgFuncNode->pNext = inst->DbgFunctionHead; + inst->DbgFunctionHead = pNewDbgFuncNode; + + *(VkDebugUtilsMessengerEXT **)pMessenger = icd_info; + pNewDbgFuncNode->messenger.messenger = *pMessenger; + +out: + + // Roll back on errors + if (VK_SUCCESS != res) { + storage_idx = 0; + for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) { + if (NULL == icd_term->dispatch.DestroyDebugUtilsMessengerEXT) { + continue; + } + + if (icd_info && icd_info[storage_idx]) { + icd_term->dispatch.DestroyDebugUtilsMessengerEXT(icd_term->instance, icd_info[storage_idx], pAllocator); + } + storage_idx++; + } + +#if (DEBUG_DISABLE_APP_ALLOCATORS == 1) + { +#else + if (pAllocator != NULL) { + if (NULL != pNewDbgFuncNode) { + pAllocator->pfnFree(pAllocator->pUserData, pNewDbgFuncNode); + } + if (NULL != icd_info) { + pAllocator->pfnFree(pAllocator->pUserData, icd_info); + } + } else { +#endif + if (NULL != pNewDbgFuncNode) { + free(pNewDbgFuncNode); + } + if (NULL != icd_info) { + free(icd_info); + } + } + } + + return res; +} + +// This is the instance chain terminator function for DestroyDebugUtilsMessenger +VKAPI_ATTR void VKAPI_CALL terminator_DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger, + const VkAllocationCallbacks *pAllocator) { + uint32_t storage_idx; + VkDebugUtilsMessengerEXT *icd_info; + const struct loader_icd_term *icd_term; + + struct loader_instance *inst = (struct loader_instance *)instance; + icd_info = *(VkDebugUtilsMessengerEXT **)&messenger; + storage_idx = 0; + for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) { + if (NULL == icd_term->dispatch.DestroyDebugUtilsMessengerEXT) { + continue; + } + + if (icd_info[storage_idx]) { + icd_term->dispatch.DestroyDebugUtilsMessengerEXT(icd_term->instance, icd_info[storage_idx], pAllocator); + } + storage_idx++; + } + +#if (DEBUG_DISABLE_APP_ALLOCATORS == 1) + { +#else + if (pAllocator != NULL) { + pAllocator->pfnFree(pAllocator->pUserData, icd_info); + } else { +#endif + free(icd_info); + } +} + +// This is the instance chain terminator function for SubmitDebugUtilsMessageEXT +VKAPI_ATTR void VKAPI_CALL terminator_SubmitDebugUtilsMessageEXT(VkInstance instance, + VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageTypes, + const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData) { + const struct loader_icd_term *icd_term; + + struct loader_instance *inst = (struct loader_instance *)instance; + + loader_platform_thread_lock_mutex(&loader_lock); + for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) { + if (icd_term->dispatch.SubmitDebugUtilsMessageEXT != NULL) { + icd_term->dispatch.SubmitDebugUtilsMessageEXT(icd_term->instance, messageSeverity, messageTypes, pCallbackData); + } + } + + // Now that all ICDs have seen the message, call the necessary callbacks. Ignoring "bail" return value + // as there is nothing to bail from at this point. + + util_SubmitDebugUtilsMessageEXT(inst, messageSeverity, messageTypes, pCallbackData); + + loader_platform_thread_unlock_mutex(&loader_lock); +} + +// VK_EXT_debug_report related items + +VkResult util_CreateDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackCreateInfoEXT *pCreateInfo, + const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT callback) { + VkLayerDbgFunctionNode *pNewDbgFuncNode = NULL; + +#if (DEBUG_DISABLE_APP_ALLOCATORS == 1) + { +#else + if (pAllocator != NULL) { + pNewDbgFuncNode = (VkLayerDbgFunctionNode *)pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(VkLayerDbgFunctionNode), + sizeof(int *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + } else { +#endif + pNewDbgFuncNode = (VkLayerDbgFunctionNode *)loader_instance_heap_alloc(inst, sizeof(VkLayerDbgFunctionNode), + VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + } + if (!pNewDbgFuncNode) { + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode)); + + pNewDbgFuncNode->is_messenger = false; + pNewDbgFuncNode->report.msgCallback = callback; + pNewDbgFuncNode->report.pfnMsgCallback = pCreateInfo->pfnCallback; + pNewDbgFuncNode->report.msgFlags = pCreateInfo->flags; + pNewDbgFuncNode->pUserData = pCreateInfo->pUserData; + pNewDbgFuncNode->pNext = inst->DbgFunctionHead; + inst->DbgFunctionHead = pNewDbgFuncNode; + + return VK_SUCCESS; +} + +static VKAPI_ATTR VkResult VKAPI_CALL +debug_utils_CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo, + const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pCallback) { + struct loader_instance *inst = loader_get_instance(instance); + loader_platform_thread_lock_mutex(&loader_lock); + VkResult result = inst->disp->layer_inst_disp.CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback); + loader_platform_thread_unlock_mutex(&loader_lock); + return result; +} + +// Utility function to handle reporting +VkBool32 util_DebugReportMessage(const struct loader_instance *inst, VkFlags msgFlags, VkDebugReportObjectTypeEXT objectType, + uint64_t srcObject, size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) { + VkBool32 bail = false; + VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead; + VkDebugUtilsMessageSeverityFlagBitsEXT severity; + VkDebugUtilsMessageTypeFlagsEXT types; + VkDebugUtilsMessengerCallbackDataEXT callback_data; + VkDebugUtilsObjectNameInfoEXT object_name; + + debug_utils_ReportFlagsToAnnotFlags(msgFlags, false, &severity, &types); + debug_utils_ReportObjectToAnnotObject(objectType, srcObject, &object_name); + + callback_data.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT; + callback_data.pNext = NULL; + callback_data.flags = 0; + callback_data.pMessageIdName = pLayerPrefix; + callback_data.messageIdNumber = msgCode; + callback_data.pMessage = pMsg; + callback_data.cmdBufLabelCount = 0; + callback_data.pCmdBufLabels = NULL; + callback_data.queueLabelCount = 0; + callback_data.pQueueLabels = NULL; + callback_data.objectCount = 1; + callback_data.pObjects = &object_name; + + while (pTrav) { + if (!pTrav->is_messenger && pTrav->report.msgFlags & msgFlags) { + if (pTrav->report.pfnMsgCallback(msgFlags, objectType, srcObject, location, msgCode, pLayerPrefix, pMsg, + pTrav->pUserData)) { + bail = true; + } + } + if (pTrav->is_messenger && (pTrav->messenger.messageSeverity & severity) && (pTrav->messenger.messageType & types)) { + if (pTrav->messenger.pfnUserCallback(severity, types, &callback_data, pTrav->pUserData)) { + bail = true; + } + } + + pTrav = pTrav->pNext; + } + + return bail; +} + +void util_DestroyDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackEXT callback, + const VkAllocationCallbacks *pAllocator) { + VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead; + VkLayerDbgFunctionNode *pPrev = pTrav; + + while (pTrav) { + if (!pTrav->is_messenger && pTrav->report.msgCallback == callback) { + pPrev->pNext = pTrav->pNext; + if (inst->DbgFunctionHead == pTrav) inst->DbgFunctionHead = pTrav->pNext; +#if (DEBUG_DISABLE_APP_ALLOCATORS == 1) + { +#else + if (pAllocator != NULL) { + pAllocator->pfnFree(pAllocator->pUserData, pTrav); + } else { +#endif + loader_instance_heap_free(inst, pTrav); + } + break; + } + pPrev = pTrav; + pTrav = pTrav->pNext; + } +} + +// This utility (used by vkInstanceCreateInfo(), looks at a pNext chain. It +// counts any VkDebugReportCallbackCreateInfoEXT structs that it finds. It +// then allocates array that can hold that many structs, as well as that many +// VkDebugReportCallbackEXT handles. It then copies each +// VkDebugReportCallbackCreateInfoEXT, and initializes each handle. +VkResult util_CopyDebugReportCreateInfos(const void *pChain, const VkAllocationCallbacks *pAllocator, uint32_t *num_callbacks, + VkDebugReportCallbackCreateInfoEXT **infos, VkDebugReportCallbackEXT **callbacks) { + uint32_t n = *num_callbacks = 0; + VkDebugReportCallbackCreateInfoEXT *pInfos = NULL; + VkDebugReportCallbackEXT *pCallbacks = NULL; + + const void *pNext = pChain; + while (pNext) { + // 1st, count the number VkDebugReportCallbackCreateInfoEXT: + if (((VkDebugReportCallbackCreateInfoEXT *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) { + n++; + } + pNext = (void *)((VkDebugReportCallbackCreateInfoEXT *)pNext)->pNext; + } + if (n == 0) { + return VK_SUCCESS; + } + +// 2nd, allocate memory for each VkDebugReportCallbackCreateInfoEXT: +#if (DEBUG_DISABLE_APP_ALLOCATORS == 1) + { +#else + if (pAllocator != NULL) { + pInfos = *infos = ((VkDebugReportCallbackCreateInfoEXT *)pAllocator->pfnAllocation( + pAllocator->pUserData, n * sizeof(VkDebugReportCallbackCreateInfoEXT), sizeof(void *), + VK_SYSTEM_ALLOCATION_SCOPE_OBJECT)); + } else { +#endif + pInfos = *infos = ((VkDebugReportCallbackCreateInfoEXT *)malloc(n * sizeof(VkDebugReportCallbackCreateInfoEXT))); + } + if (!pInfos) { + return VK_ERROR_OUT_OF_HOST_MEMORY; + } +// 3rd, allocate memory for a unique handle for each callback: +#if (DEBUG_DISABLE_APP_ALLOCATORS == 1) + { +#else + if (pAllocator != NULL) { + pCallbacks = *callbacks = ((VkDebugReportCallbackEXT *)pAllocator->pfnAllocation( + pAllocator->pUserData, n * sizeof(VkDebugReportCallbackEXT), sizeof(void *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT)); + if (!pCallbacks) { + pAllocator->pfnFree(pAllocator->pUserData, pInfos); + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + } else { +#endif + pCallbacks = *callbacks = ((VkDebugReportCallbackEXT *)malloc(n * sizeof(VkDebugReportCallbackEXT))); + if (!pCallbacks) { + free(pInfos); + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + } + // 4th, copy each VkDebugReportCallbackCreateInfoEXT for use by + // vkDestroyInstance, and assign a unique handle to each callback (just + // use the address of the copied VkDebugReportCallbackCreateInfoEXT): + pNext = pChain; + while (pNext) { + if (((VkInstanceCreateInfo *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) { + memcpy(pInfos, pNext, sizeof(VkDebugReportCallbackCreateInfoEXT)); + *pCallbacks++ = (VkDebugReportCallbackEXT)(uintptr_t)pInfos++; + } + pNext = (void *)((VkInstanceCreateInfo *)pNext)->pNext; + } + + *num_callbacks = n; + return VK_SUCCESS; +} + +void util_FreeDebugReportCreateInfos(const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackCreateInfoEXT *infos, + VkDebugReportCallbackEXT *callbacks) { +#if (DEBUG_DISABLE_APP_ALLOCATORS == 1) + { +#else + if (pAllocator != NULL) { + pAllocator->pfnFree(pAllocator->pUserData, infos); + pAllocator->pfnFree(pAllocator->pUserData, callbacks); + } else { +#endif + free(infos); + free(callbacks); + } +} + +VkResult util_CreateDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator, + uint32_t num_callbacks, VkDebugReportCallbackCreateInfoEXT *infos, + VkDebugReportCallbackEXT *callbacks) { + VkResult rtn = VK_SUCCESS; + for (uint32_t i = 0; i < num_callbacks; i++) { + rtn = util_CreateDebugReportCallback(inst, &infos[i], pAllocator, callbacks[i]); + if (rtn != VK_SUCCESS) { + for (uint32_t j = 0; j < i; j++) { + util_DestroyDebugReportCallback(inst, callbacks[j], pAllocator); + } + return rtn; + } + } + return rtn; +} + +void util_DestroyDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator, uint32_t num_callbacks, + VkDebugReportCallbackEXT *callbacks) { + for (uint32_t i = 0; i < num_callbacks; i++) { + util_DestroyDebugReportCallback(inst, callbacks[i], pAllocator); + } +} + +static VKAPI_ATTR void VKAPI_CALL debug_utils_DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback, + const VkAllocationCallbacks *pAllocator) { + struct loader_instance *inst = loader_get_instance(instance); + loader_platform_thread_lock_mutex(&loader_lock); + + inst->disp->layer_inst_disp.DestroyDebugReportCallbackEXT(instance, callback, pAllocator); + + util_DestroyDebugReportCallback(inst, callback, pAllocator); + + loader_platform_thread_unlock_mutex(&loader_lock); +} + +static VKAPI_ATTR void VKAPI_CALL debug_utils_DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, + VkDebugReportObjectTypeEXT objType, uint64_t object, + size_t location, int32_t msgCode, const char *pLayerPrefix, + const char *pMsg) { + struct loader_instance *inst = loader_get_instance(instance); + + inst->disp->layer_inst_disp.DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg); +} + +// This is the instance chain terminator function +// for CreateDebugReportCallback +VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugReportCallbackEXT(VkInstance instance, + const VkDebugReportCallbackCreateInfoEXT *pCreateInfo, + const VkAllocationCallbacks *pAllocator, + VkDebugReportCallbackEXT *pCallback) { + VkDebugReportCallbackEXT *icd_info = NULL; + const struct loader_icd_term *icd_term; + struct loader_instance *inst = (struct loader_instance *)instance; + VkResult res = VK_SUCCESS; + uint32_t storage_idx; + VkLayerDbgFunctionNode *pNewDbgFuncNode = NULL; + +#if (DEBUG_DISABLE_APP_ALLOCATORS == 1) + { +#else + if (pAllocator != NULL) { + icd_info = ((VkDebugReportCallbackEXT *)pAllocator->pfnAllocation(pAllocator->pUserData, + inst->total_icd_count * sizeof(VkDebugReportCallbackEXT), + sizeof(void *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT)); + if (icd_info) { + memset(icd_info, 0, inst->total_icd_count * sizeof(VkDebugReportCallbackEXT)); + } + } else { +#endif + icd_info = calloc(sizeof(VkDebugReportCallbackEXT), inst->total_icd_count); + } + if (!icd_info) { + res = VK_ERROR_OUT_OF_HOST_MEMORY; + goto out; + } + + storage_idx = 0; + for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) { + if (!icd_term->dispatch.CreateDebugReportCallbackEXT) { + continue; + } + + res = icd_term->dispatch.CreateDebugReportCallbackEXT(icd_term->instance, pCreateInfo, pAllocator, &icd_info[storage_idx]); + + if (res != VK_SUCCESS) { + goto out; + } + storage_idx++; + } + +// Setup the debug report callback in the terminator since a layer may want +// to grab the information itself (RenderDoc) and then return back to the +// user callback a sub-set of the messages. +#if (DEBUG_DISABLE_APP_ALLOCATORS == 0) + if (pAllocator != NULL) { + pNewDbgFuncNode = (VkLayerDbgFunctionNode *)pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(VkLayerDbgFunctionNode), + sizeof(int *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + } else { +#else + { +#endif + pNewDbgFuncNode = (VkLayerDbgFunctionNode *)loader_instance_heap_alloc(inst, sizeof(VkLayerDbgFunctionNode), + VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + } + if (!pNewDbgFuncNode) { + res = VK_ERROR_OUT_OF_HOST_MEMORY; + goto out; + } + memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode)); + + pNewDbgFuncNode->is_messenger = false; + pNewDbgFuncNode->report.pfnMsgCallback = pCreateInfo->pfnCallback; + pNewDbgFuncNode->report.msgFlags = pCreateInfo->flags; + pNewDbgFuncNode->pUserData = pCreateInfo->pUserData; + pNewDbgFuncNode->pNext = inst->DbgFunctionHead; + inst->DbgFunctionHead = pNewDbgFuncNode; + + *(VkDebugReportCallbackEXT **)pCallback = icd_info; + pNewDbgFuncNode->report.msgCallback = *pCallback; + +out: + + // Roll back on errors + if (VK_SUCCESS != res) { + storage_idx = 0; + for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) { + if (NULL == icd_term->dispatch.DestroyDebugReportCallbackEXT) { + continue; + } + + if (icd_info && icd_info[storage_idx]) { + icd_term->dispatch.DestroyDebugReportCallbackEXT(icd_term->instance, icd_info[storage_idx], pAllocator); + } + storage_idx++; + } + +#if (DEBUG_DISABLE_APP_ALLOCATORS == 1) + { +#else + if (pAllocator != NULL) { + if (NULL != pNewDbgFuncNode) { + pAllocator->pfnFree(pAllocator->pUserData, pNewDbgFuncNode); + } + if (NULL != icd_info) { + pAllocator->pfnFree(pAllocator->pUserData, icd_info); + } + } else { +#endif + if (NULL != pNewDbgFuncNode) { + free(pNewDbgFuncNode); + } + if (NULL != icd_info) { + free(icd_info); + } + } + } + + return res; +} + +// This is the instance chain terminator function for DestroyDebugReportCallback +VKAPI_ATTR void VKAPI_CALL terminator_DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback, + const VkAllocationCallbacks *pAllocator) { + uint32_t storage_idx; + VkDebugReportCallbackEXT *icd_info; + const struct loader_icd_term *icd_term; + + struct loader_instance *inst = (struct loader_instance *)instance; + icd_info = *(VkDebugReportCallbackEXT **)&callback; + storage_idx = 0; + for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) { + if (NULL == icd_term->dispatch.DestroyDebugReportCallbackEXT) { + continue; + } + + if (icd_info[storage_idx]) { + icd_term->dispatch.DestroyDebugReportCallbackEXT(icd_term->instance, icd_info[storage_idx], pAllocator); + } + storage_idx++; + } + +#if (DEBUG_DISABLE_APP_ALLOCATORS == 1) + { +#else + if (pAllocator != NULL) { + pAllocator->pfnFree(pAllocator->pUserData, icd_info); + } else { +#endif + free(icd_info); + } +} + +// This is the instance chain terminator function for DebugReportMessage +VKAPI_ATTR void VKAPI_CALL terminator_DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, + VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location, + int32_t msgCode, const char *pLayerPrefix, const char *pMsg) { + const struct loader_icd_term *icd_term; + + struct loader_instance *inst = (struct loader_instance *)instance; + + loader_platform_thread_lock_mutex(&loader_lock); + for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) { + if (icd_term->dispatch.DebugReportMessageEXT != NULL) { + icd_term->dispatch.DebugReportMessageEXT(icd_term->instance, flags, objType, object, location, msgCode, pLayerPrefix, + pMsg); + } + } + + // Now that all ICDs have seen the message, call the necessary callbacks. Ignoring "bail" return value + // as there is nothing to bail from at this point. + + util_DebugReportMessage(inst, flags, objType, object, location, msgCode, pLayerPrefix, pMsg); + + loader_platform_thread_unlock_mutex(&loader_lock); +} + +// General utilities + +static const VkExtensionProperties debug_utils_extension_info[] = { + {VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}, + {VK_EXT_DEBUG_UTILS_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_SPEC_VERSION}, +}; + +void debug_utils_AddInstanceExtensions(const struct loader_instance *inst, struct loader_extension_list *ext_list) { + loader_add_to_ext_list(inst, ext_list, sizeof(debug_utils_extension_info) / sizeof(VkExtensionProperties), + debug_utils_extension_info); +} + +void debug_utils_CreateInstance(struct loader_instance *ptr_instance, const VkInstanceCreateInfo *pCreateInfo) { + ptr_instance->enabled_known_extensions.ext_debug_report = 0; + ptr_instance->enabled_known_extensions.ext_debug_utils = 0; + + for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) { + if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0) { + ptr_instance->enabled_known_extensions.ext_debug_report = 1; + } else if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_EXT_DEBUG_UTILS_EXTENSION_NAME) == 0) { + ptr_instance->enabled_known_extensions.ext_debug_utils = 1; + } + } +} + +bool debug_utils_InstanceGpa(struct loader_instance *ptr_instance, const char *name, void **addr) { + bool ret_type = false; + + *addr = NULL; + + if (ptr_instance->enabled_known_extensions.ext_debug_report == 1) { + if (!strcmp("vkCreateDebugReportCallbackEXT", name)) { + *addr = (void *)debug_utils_CreateDebugReportCallbackEXT; + ret_type = true; + } else if (!strcmp("vkDestroyDebugReportCallbackEXT", name)) { + *addr = (void *)debug_utils_DestroyDebugReportCallbackEXT; + ret_type = true; + } else if (!strcmp("vkDebugReportMessageEXT", name)) { + *addr = (void *)debug_utils_DebugReportMessageEXT; + return true; + } + } + if (ptr_instance->enabled_known_extensions.ext_debug_utils == 1) { + if (!strcmp("vkCreateDebugUtilsMessengerEXT", name)) { + *addr = (void *)debug_utils_CreateDebugUtilsMessengerEXT; + ret_type = true; + } else if (!strcmp("vkDestroyDebugUtilsMessengerEXT", name)) { + *addr = (void *)debug_utils_DestroyDebugUtilsMessengerEXT; + ret_type = true; + } else if (!strcmp("vkSubmitDebugUtilsMessageEXT", name)) { + *addr = (void *)debug_utils_SubmitDebugUtilsMessageEXT; + ret_type = true; + } + } + + return ret_type; +} + +bool debug_utils_ReportFlagsToAnnotFlags(VkDebugReportFlagsEXT dr_flags, bool default_flag_is_spec, + VkDebugUtilsMessageSeverityFlagBitsEXT *da_severity, + VkDebugUtilsMessageTypeFlagsEXT *da_type) { + bool type_set = false; + if (NULL == da_severity || NULL == da_type) { + return false; + } + *da_type = 0; + + 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; + type_set = true; + } else if ((dr_flags & (VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT)) != 0) { + *da_severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT; + } else if ((dr_flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) != 0) { + *da_severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; + } else 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; + type_set = true; + } + + if ((dr_flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) != 0) { + *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; + } else if (!type_set) { + if (default_flag_is_spec) { + *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT; + } else { + *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT; + } + } + + return true; +} + +bool debug_utils_AnnotFlagsToReportFlags(VkDebugUtilsMessageSeverityFlagBitsEXT da_severity, + VkDebugUtilsMessageTypeFlagsEXT da_type, VkDebugReportFlagsEXT *dr_flags) { + if (NULL == dr_flags) { + return false; + } + + *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; + } + + return true; +} + +bool debug_utils_ReportObjectToAnnotObject(VkDebugReportObjectTypeEXT dr_object_type, uint64_t object_handle, + VkDebugUtilsObjectNameInfoEXT *da_object_name_info) { + if (NULL == da_object_name_info) { + return false; + } + da_object_name_info->sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT; + da_object_name_info->pNext = NULL; + da_object_name_info->objectHandle = (uint64_t)(uintptr_t)object_handle; + da_object_name_info->pObjectName = NULL; + da_object_name_info->objectType = convertDebugReportObjectToCoreObject(dr_object_type); + return true; +} + +bool debug_utils_AnnotObjectToDebugReportObject(const VkDebugUtilsObjectNameInfoEXT *da_object_name_info, + VkDebugReportObjectTypeEXT *dr_object_type, uint64_t *dr_object_handle) { + if (NULL == da_object_name_info || NULL == dr_object_type || NULL == dr_object_handle) { + return false; + } + *dr_object_type = convertCoreObjectToDebugReportObject(da_object_name_info->objectType); + *dr_object_handle = da_object_name_info->objectHandle; + return true; +} diff --git a/loader/debug_utils.h b/loader/debug_utils.h new file mode 100644 index 00000000..c33a6fce --- /dev/null +++ b/loader/debug_utils.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2015-2017 The Khronos Group Inc. + * Copyright (c) 2015-2017 Valve Corporation + * Copyright (c) 2015-2017 LunarG, Inc. + * Copyright (C) 2015-2016 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Author: Courtney Goeltzenleuchter <courtney@LunarG.com> + * Author: Jon Ashburn <jon@lunarg.com> + * Author: Mark Young <markyk@lunarg.com> + * + */ + +#include "vk_loader_platform.h" +#include "loader.h" + +// General utilities + +void debug_utils_AddInstanceExtensions(const struct loader_instance *inst, struct loader_extension_list *ext_list); +void debug_utils_CreateInstance(struct loader_instance *ptr_instance, const VkInstanceCreateInfo *pCreateInfo); +bool debug_utils_InstanceGpa(struct loader_instance *ptr_instance, const char *name, void **addr); +bool debug_utils_ReportFlagsToAnnotFlags(VkDebugReportFlagsEXT dr_flags, bool default_flag_is_spec, + VkDebugUtilsMessageSeverityFlagBitsEXT *da_severity, + VkDebugUtilsMessageTypeFlagsEXT *da_type); +bool debug_utils_AnnotFlagsToReportFlags(VkDebugUtilsMessageSeverityFlagBitsEXT da_severity, + VkDebugUtilsMessageTypeFlagsEXT da_type, VkDebugReportFlagsEXT *dr_flags); +bool debug_utils_ReportObjectToAnnotObject(VkDebugReportObjectTypeEXT dr_object_type, uint64_t object_handle, + VkDebugUtilsObjectNameInfoEXT *da_object_name_info); +bool debug_utils_AnnotObjectToDebugReportObject(const VkDebugUtilsObjectNameInfoEXT *da_object_name_info, + VkDebugReportObjectTypeEXT *dr_object_type, uint64_t *dr_object_handle); + +// VK_EXT_debug_utils related items + +VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugUtilsMessengerEXT(VkInstance instance, + const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo, + const VkAllocationCallbacks *pAllocator, + VkDebugUtilsMessengerEXT *pMessenger); +VKAPI_ATTR void VKAPI_CALL terminator_DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger, + const VkAllocationCallbacks *pAllocator); +VKAPI_ATTR void VKAPI_CALL terminator_SubmitDebugUtilsMessageEXT(VkInstance instance, + VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageTypes, + const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData); +VkResult util_CreateDebugUtilsMessenger(struct loader_instance *inst, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo, + const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerEXT messenger); +VkResult util_CreateDebugUtilsMessengers(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator, + uint32_t num_messengers, VkDebugUtilsMessengerCreateInfoEXT *infos, + VkDebugUtilsMessengerEXT *messengers); +VkBool32 util_SubmitDebugUtilsMessageEXT(const struct loader_instance *inst, VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageTypes, + const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData); +VkResult util_CopyDebugUtilsMessengerCreateInfos(const void *pChain, const VkAllocationCallbacks *pAllocator, + uint32_t *num_messengers, VkDebugUtilsMessengerCreateInfoEXT **infos, + VkDebugUtilsMessengerEXT **messengers); +void util_DestroyDebugUtilsMessenger(struct loader_instance *inst, VkDebugUtilsMessengerEXT messenger, + const VkAllocationCallbacks *pAllocator); +void util_DestroyDebugUtilsMessengers(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator, + uint32_t num_messengers, VkDebugUtilsMessengerEXT *messengers); +void util_FreeDebugUtilsMessengerCreateInfos(const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerCreateInfoEXT *infos, + VkDebugUtilsMessengerEXT *messengers); + +// VK_EXT_debug_report related items + +VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugReportCallbackEXT(VkInstance instance, + const VkDebugReportCallbackCreateInfoEXT *pCreateInfo, + const VkAllocationCallbacks *pAllocator, + VkDebugReportCallbackEXT *pCallback); + +VKAPI_ATTR void VKAPI_CALL terminator_DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback, + const VkAllocationCallbacks *pAllocator); + +VKAPI_ATTR void VKAPI_CALL terminator_DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, + VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location, + int32_t msgCode, const char *pLayerPrefix, const char *pMsg); + +VkResult util_CreateDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackCreateInfoEXT *pCreateInfo, + const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT callback); +VkResult util_CreateDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator, + uint32_t num_callbacks, VkDebugReportCallbackCreateInfoEXT *infos, + VkDebugReportCallbackEXT *callbacks); +VkBool32 util_DebugReportMessage(const struct loader_instance *inst, VkFlags msgFlags, VkDebugReportObjectTypeEXT objectType, + uint64_t srcObject, size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg); +VkResult util_CopyDebugReportCreateInfos(const void *pChain, const VkAllocationCallbacks *pAllocator, uint32_t *num_callbacks, + VkDebugReportCallbackCreateInfoEXT **infos, VkDebugReportCallbackEXT **callbacks); +void util_DestroyDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackEXT callback, + const VkAllocationCallbacks *pAllocator); +void util_DestroyDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator, uint32_t num_callbacks, + VkDebugReportCallbackEXT *callbacks); +void util_FreeDebugReportCreateInfos(const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackCreateInfoEXT *infos, + VkDebugReportCallbackEXT *callbacks); diff --git a/loader/extension_manual.c b/loader/extension_manual.c index 65c625ea..2b70af70 100644 --- a/loader/extension_manual.c +++ b/loader/extension_manual.c @@ -28,7 +28,7 @@ #include "vk_loader_extensions.h" #include <vulkan/vk_icd.h> #include "wsi.h" -#include "debug_report.h" +#include "debug_utils.h" // ---- Manually added trampoline/terminator functions diff --git a/loader/gpa_helper.h b/loader/gpa_helper.h index 463e352b..1196edf5 100644 --- a/loader/gpa_helper.h +++ b/loader/gpa_helper.h @@ -20,7 +20,7 @@ */ #include <string.h> -#include "debug_report.h" +#include "debug_utils.h" #include "wsi.h" static inline void *trampolineGetProcAddr(struct loader_instance *inst, const char *funcName) { @@ -189,7 +189,7 @@ static inline void *trampolineGetProcAddr(struct loader_instance *inst, const ch // Instance extensions void *addr; - if (debug_report_instance_gpa(inst, funcName, &addr)) return addr; + if (debug_utils_InstanceGpa(inst, funcName, &addr)) return addr; if (wsi_swapchain_instance_gpa(inst, funcName, &addr)) return addr; diff --git a/loader/loader.c b/loader/loader.c index d4e0e026..92be90b7 100644 --- a/loader/loader.c +++ b/loader/loader.c @@ -45,7 +45,7 @@ #include "vk_loader_platform.h" #include "loader.h" #include "gpa_helper.h" -#include "debug_report.h" +#include "debug_utils.h" #include "wsi.h" #include "vulkan/vk_icd.h" #include "cJSON.h" @@ -322,8 +322,46 @@ void loader_log(const struct loader_instance *inst, VkFlags msg_type, int32_t ms va_end(ap); if (inst) { - util_DebugReportMessage(inst, msg_type, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, (uint64_t)(uintptr_t)inst, 0, msg_code, - "loader", msg); + VkDebugUtilsMessageSeverityFlagBitsEXT severity; + VkDebugUtilsMessageTypeFlagsEXT type; + VkDebugUtilsMessengerCallbackDataEXT callback_data; + VkDebugUtilsObjectNameInfoEXT object_name; + + if ((msg_type & LOADER_INFO_BIT) != 0) { + severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT; + } else if ((msg_type & LOADER_WARN_BIT) != 0) { + severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT; + } else if ((msg_type & LOADER_ERROR_BIT) != 0) { + severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; + } else if ((msg_type & LOADER_DEBUG_BIT) != 0) { + severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT; + } + + if ((msg_type & LOADER_PERF_BIT) != 0) { + type = VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; + } else { + type = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT; + } + + callback_data.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT; + callback_data.pNext = NULL; + callback_data.flags = 0; + callback_data.pMessageIdName = "Loader Message"; + callback_data.messageIdNumber = 0; + callback_data.pMessage = msg; + 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; + object_name.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT; + object_name.pNext = NULL; + object_name.objectType = VK_OBJECT_TYPE_INSTANCE; + object_name.objectHandle = (uint64_t)(uintptr_t)inst; + object_name.pObjectName = NULL; + + util_SubmitDebugUtilsMessageEXT(inst, severity, type, &callback_data); } if (!(msg_type & g_loader_log_msgs)) { @@ -1608,7 +1646,7 @@ VkResult loader_get_icd_loader_instance_extensions(const struct loader_instance }; // Traverse loader's extensions, adding non-duplicate extensions to the list - debug_report_add_instance_extensions(inst, inst_exts); + debug_utils_AddInstanceExtensions(inst, inst_exts); out: return res; diff --git a/loader/loader.h b/loader/loader.h index ae928f95..9342e21c 100644 --- a/loader/loader.h +++ b/loader/loader.h @@ -276,9 +276,12 @@ struct loader_instance { union loader_instance_extension_enables enabled_known_extensions; VkLayerDbgFunctionNode *DbgFunctionHead; - 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_messengers; + VkDebugUtilsMessengerCreateInfoEXT *tmp_messenger_create_infos; + VkDebugUtilsMessengerEXT *tmp_messengers; VkAllocationCallbacks alloc_callbacks; diff --git a/loader/trampoline.c b/loader/trampoline.c index 7915006d..6b0464d4 100644 --- a/loader/trampoline.c +++ b/loader/trampoline.c @@ -28,7 +28,7 @@ #include "vk_loader_platform.h" #include "loader.h" -#include "debug_report.h" +#include "debug_utils.h" #include "wsi.h" #include "vk_loader_extensions.h" #include "gpa_helper.h" @@ -324,23 +324,42 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCr ptr_instance->app_api_minor_version = VK_VERSION_MINOR(pCreateInfo->pApplicationInfo->apiVersion); } - // Look for one or more debug report create info structures + // Look for one or more VK_EXT_debug_report or VK_EXT_debug_utils create info structures // and setup a callback(s) for each one found. - ptr_instance->num_tmp_callbacks = 0; - ptr_instance->tmp_dbg_create_infos = NULL; - ptr_instance->tmp_callbacks = NULL; - if (util_CopyDebugReportCreateInfos(pCreateInfo->pNext, pAllocator, &ptr_instance->num_tmp_callbacks, - &ptr_instance->tmp_dbg_create_infos, &ptr_instance->tmp_callbacks)) { - // One or more were found, but allocation failed. Therefore, clean up - // and fail this function: + ptr_instance->num_tmp_report_callbacks = 0; + ptr_instance->tmp_report_create_infos = NULL; + ptr_instance->tmp_report_callbacks = NULL; + ptr_instance->num_tmp_messengers = 0; + ptr_instance->tmp_messenger_create_infos = NULL; + ptr_instance->tmp_messengers = NULL; + + // Handle cases of VK_EXT_debug_utils + if (util_CopyDebugUtilsMessengerCreateInfos(pCreateInfo->pNext, pAllocator, &ptr_instance->num_tmp_messengers, + &ptr_instance->tmp_messenger_create_infos, &ptr_instance->tmp_messengers)) { + // One or more were found, but allocation failed. Therefore, clean up and fail this function: res = VK_ERROR_OUT_OF_HOST_MEMORY; goto out; - } else if (ptr_instance->num_tmp_callbacks > 0) { + } else if (ptr_instance->num_tmp_messengers > 0) { + // Setup the temporary messenger(s) here to catch early issues: + if (util_CreateDebugUtilsMessengers(ptr_instance, pAllocator, ptr_instance->num_tmp_messengers, + ptr_instance->tmp_messenger_create_infos, ptr_instance->tmp_messengers)) { + // Failure of setting up one or more of the messenger. Therefore, clean up and fail this function: + res = VK_ERROR_OUT_OF_HOST_MEMORY; + goto out; + } + } + + // Handle cases of VK_EXT_debug_report + if (util_CopyDebugReportCreateInfos(pCreateInfo->pNext, pAllocator, &ptr_instance->num_tmp_report_callbacks, + &ptr_instance->tmp_report_create_infos, &ptr_instance->tmp_report_callbacks)) { + // One or more were found, but allocation failed. Therefore, clean up and fail this function: + res = VK_ERROR_OUT_OF_HOST_MEMORY; + goto out; + } else if (ptr_instance->num_tmp_report_callbacks > 0) { // Setup the temporary callback(s) here to catch early issues: - if (util_CreateDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_callbacks, - ptr_instance->tmp_dbg_create_infos, ptr_instance->tmp_callbacks)) { - // Failure of setting up one or more of the callback. Therefore, - // clean up and fail this function: + if (util_CreateDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_report_callbacks, + ptr_instance->tmp_report_create_infos, ptr_instance->tmp_report_callbacks)) { + // Failure of setting up one or more of the callback. Therefore, clean up and fail this function: res = VK_ERROR_OUT_OF_HOST_MEMORY; goto out; } @@ -404,7 +423,7 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCr memset(ptr_instance->enabled_known_extensions.padding, 0, sizeof(uint64_t) * 4); wsi_create_instance(ptr_instance, &ici); - debug_report_create_instance(ptr_instance, &ici); + debug_utils_CreateInstance(ptr_instance, &ici); extensions_create_instance(ptr_instance, &ici); *pInstance = created_instance; @@ -426,10 +445,19 @@ out: if (NULL != ptr_instance->disp) { loader_instance_heap_free(ptr_instance, ptr_instance->disp); } - if (ptr_instance->num_tmp_callbacks > 0) { - util_DestroyDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_callbacks, - ptr_instance->tmp_callbacks); - util_FreeDebugReportCreateInfos(pAllocator, ptr_instance->tmp_dbg_create_infos, ptr_instance->tmp_callbacks); + if (ptr_instance->num_tmp_report_callbacks > 0) { + // Remove temporary VK_EXT_debug_report items + util_DestroyDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_report_callbacks, + ptr_instance->tmp_report_callbacks); + util_FreeDebugReportCreateInfos(pAllocator, ptr_instance->tmp_report_create_infos, + ptr_instance->tmp_report_callbacks); + } + if (ptr_instance->num_tmp_messengers > 0) { + // Remove temporary VK_EXT_debug_utils items + util_DestroyDebugUtilsMessengers(ptr_instance, pAllocator, ptr_instance->num_tmp_messengers, + ptr_instance->tmp_messengers); + util_FreeDebugUtilsMessengerCreateInfos(pAllocator, ptr_instance->tmp_messenger_create_infos, + ptr_instance->tmp_messengers); } if (NULL != ptr_instance->expanded_activated_layer_list.list) { @@ -445,9 +473,11 @@ out: loader_instance_heap_free(ptr_instance, ptr_instance); } else { - // Remove temporary debug_report callback - util_DestroyDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_callbacks, - ptr_instance->tmp_callbacks); + // Remove temporary VK_EXT_debug_report or VK_EXT_debug_utils items + util_DestroyDebugUtilsMessengers(ptr_instance, pAllocator, ptr_instance->num_tmp_messengers, + ptr_instance->tmp_messengers); + util_DestroyDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_report_callbacks, + ptr_instance->tmp_report_callbacks); } if (loaderLocked) { @@ -462,6 +492,7 @@ LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance, const VkLayerInstanceDispatchTable *disp; struct loader_instance *ptr_instance = NULL; bool callback_setup = false; + bool messenger_setup = false; if (instance == VK_NULL_HANDLE) { return; @@ -477,10 +508,18 @@ LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance, ptr_instance->alloc_callbacks = *pAllocator; } - if (ptr_instance->num_tmp_callbacks > 0) { - // Setup the temporary callback(s) here to catch cleanup issues: - if (!util_CreateDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_callbacks, - ptr_instance->tmp_dbg_create_infos, ptr_instance->tmp_callbacks)) { + if (ptr_instance->num_tmp_messengers > 0) { + // Setup the temporary VK_EXT_debug_utils messenger(s) here to catch cleanup issues: + if (!util_CreateDebugUtilsMessengers(ptr_instance, pAllocator, ptr_instance->num_tmp_messengers, + ptr_instance->tmp_messenger_create_infos, ptr_instance->tmp_messengers)) { + messenger_setup = true; + } + } + + if (ptr_instance->num_tmp_report_callbacks > 0) { + // Setup the temporary VK_EXT_debug_report callback(s) here to catch cleanup issues: + if (!util_CreateDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_report_callbacks, + ptr_instance->tmp_report_create_infos, ptr_instance->tmp_report_callbacks)) { callback_setup = true; } } @@ -508,9 +547,15 @@ LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance, loader_instance_heap_free(ptr_instance, ptr_instance->phys_dev_groups_tramp); } + if (messenger_setup) { + util_DestroyDebugUtilsMessengers(ptr_instance, pAllocator, ptr_instance->num_tmp_messengers, ptr_instance->tmp_messengers); + util_FreeDebugUtilsMessengerCreateInfos(pAllocator, ptr_instance->tmp_messenger_create_infos, ptr_instance->tmp_messengers); + } + if (callback_setup) { - util_DestroyDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_callbacks, ptr_instance->tmp_callbacks); - util_FreeDebugReportCreateInfos(pAllocator, ptr_instance->tmp_dbg_create_infos, ptr_instance->tmp_callbacks); + util_DestroyDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_report_callbacks, + ptr_instance->tmp_report_callbacks); + util_FreeDebugReportCreateInfos(pAllocator, ptr_instance->tmp_report_create_infos, ptr_instance->tmp_report_callbacks); } loader_instance_heap_free(ptr_instance, ptr_instance->disp); loader_instance_heap_free(ptr_instance, ptr_instance); diff --git a/loader/vk_loader_layer.h b/loader/vk_loader_layer.h index 425154d8..dfcf5b2a 100644 --- a/loader/vk_loader_layer.h +++ b/loader/vk_loader_layer.h @@ -21,11 +21,26 @@ */ #pragma once -// Linked list node for tree of debug callback functions -typedef struct VkLayerDbgFunctionNode_ { +// Linked list node for tree of debug callbacks +typedef struct VkDebugReportContent { VkDebugReportCallbackEXT msgCallback; PFN_vkDebugReportCallbackEXT pfnMsgCallback; VkFlags msgFlags; +} VkDebugReportContent; + +typedef struct VkDebugUtilsMessengerContent { + VkDebugUtilsMessengerEXT messenger; + VkDebugUtilsMessageSeverityFlagsEXT messageSeverity; + VkDebugUtilsMessageTypeFlagsEXT messageType; + PFN_vkDebugUtilsMessengerCallbackEXT pfnUserCallback; +} VkDebugUtilsMessengerContent; + +typedef struct VkLayerDbgFunctionNode_ { + bool is_messenger; + union { + VkDebugReportContent report; + VkDebugUtilsMessengerContent messenger; + }; void *pUserData; struct VkLayerDbgFunctionNode_ *pNext; } VkLayerDbgFunctionNode; diff --git a/scripts/helper_file_generator.py b/scripts/helper_file_generator.py index fb519b67..e460f964 100644 --- a/scripts/helper_file_generator.py +++ b/scripts/helper_file_generator.py @@ -747,7 +747,8 @@ class HelperFileOutputGenerator(OutputGenerator): # # Object types header: create object enum type header file def GenerateObjectTypesHeader(self): - object_types_header = '// Object Type enum for validation layer internal object handling\n' + object_types_header = '' + object_types_header += '// Object Type enum for validation layer internal object handling\n' object_types_header += 'typedef enum VulkanObjectType {\n' object_types_header += ' kVulkanObjectTypeUnknown = 0,\n' enum_num = 1 @@ -777,7 +778,7 @@ class HelperFileOutputGenerator(OutputGenerator): object_types_header += '\n' object_types_header += '// Helper array to get Vulkan VK_EXT_debug_report object type enum from the internal layers version\n' object_types_header += 'const VkDebugReportObjectTypeEXT get_debug_report_enum[] = {\n' - object_types_header += ' VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, // No Match\n' + object_types_header += ' VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, // kVulkanObjectTypeUnknown\n' for object_type in type_list: search_type = object_type.replace("kVulkanObjectType", "").lower() for vk_object_type in self.debug_report_object_types: @@ -793,7 +794,7 @@ class HelperFileOutputGenerator(OutputGenerator): object_types_header += '\n' object_types_header += '// Helper array to get Official Vulkan VkObjectType enum from the internal layers version\n' object_types_header += 'const VkObjectType get_object_type_enum[] = {\n' - object_types_header += ' VK_OBJECT_TYPE_UNKNOWN, // No Match\n' + object_types_header += ' VK_OBJECT_TYPE_UNKNOWN, // kVulkanObjectTypeUnknown\n' for object_type in type_list: search_type = object_type.replace("kVulkanObjectType", "").lower() for vk_object_type in self.core_object_types: @@ -804,6 +805,47 @@ class HelperFileOutputGenerator(OutputGenerator): break object_types_header += '};\n' + # Create a function to convert from VkDebugReportObjectTypeEXT to VkObjectType + object_types_header += '\n' + object_types_header += '// Helper function to convert from VkDebugReportObjectTypeEXT to VkObjectType\n' + object_types_header += 'static VkObjectType convertDebugReportObjectToCoreObject(VkDebugReportObjectTypeEXT debug_report_obj){\n' + object_types_header += ' if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT) {\n' + object_types_header += ' return VK_OBJECT_TYPE_UNKNOWN;\n' + for core_object_type in self.core_object_types: + core_target_type = core_object_type.replace("VK_OBJECT_TYPE_", "").lower() + core_target_type = core_target_type.replace("_", "") + for dr_object_type in self.debug_report_object_types: + dr_target_type = dr_object_type.replace("VK_DEBUG_REPORT_OBJECT_TYPE_", "").lower() + dr_target_type = dr_target_type[:-4] + dr_target_type = dr_target_type.replace("_", "") + if core_target_type == dr_target_type: + object_types_header += ' } else if (debug_report_obj == %s) {\n' % dr_object_type + object_types_header += ' return %s;\n' % core_object_type + break + object_types_header += ' }\n' + object_types_header += ' return VK_OBJECT_TYPE_UNKNOWN;\n' + object_types_header += '}\n' + + # Create a function to convert from VkObjectType to VkDebugReportObjectTypeEXT + object_types_header += '\n' + object_types_header += '// Helper function to convert from VkDebugReportObjectTypeEXT to VkObjectType\n' + object_types_header += 'static VkDebugReportObjectTypeEXT convertCoreObjectToDebugReportObject(VkObjectType core_report_obj){\n' + object_types_header += ' if (core_report_obj == VK_OBJECT_TYPE_UNKNOWN) {\n' + object_types_header += ' return VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT;\n' + for core_object_type in self.core_object_types: + core_target_type = core_object_type.replace("VK_OBJECT_TYPE_", "").lower() + core_target_type = core_target_type.replace("_", "") + for dr_object_type in self.debug_report_object_types: + dr_target_type = dr_object_type.replace("VK_DEBUG_REPORT_OBJECT_TYPE_", "").lower() + dr_target_type = dr_target_type[:-4] + dr_target_type = dr_target_type.replace("_", "") + if core_target_type == dr_target_type: + object_types_header += ' } else if (core_report_obj == %s) {\n' % core_object_type + object_types_header += ' return %s;\n' % dr_object_type + break + object_types_header += ' }\n' + object_types_header += ' return VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT;\n' + object_types_header += '}\n' return object_types_header # # Determine if a structure needs a safe_struct helper function diff --git a/scripts/loader_extension_generator.py b/scripts/loader_extension_generator.py index a4a3f8fb..ae2b3dac 100644 --- a/scripts/loader_extension_generator.py +++ b/scripts/loader_extension_generator.py @@ -40,14 +40,25 @@ WSI_EXT_NAMES = ['VK_KHR_surface', 'VK_KHR_swapchain', 'VK_KHR_display_swapchain'] +ADD_INST_CMDS = ['vkCreateInstance', + 'vkEnumerateInstanceExtensionProperties', + 'vkEnumerateInstanceLayerProperties', + 'vkEnumerateInstanceVersion'] + AVOID_EXT_NAMES = ['VK_EXT_debug_report'] +AVOID_CMD_NAMES = ['vkCreateDebugUtilsMessengerEXT', + 'vkDestroyDebugUtilsMessengerEXT', + 'vkSubmitDebugUtilsMessageEXT'] + DEVICE_CMDS_NEED_TERM = ['vkGetDeviceProcAddr', 'vkCreateSwapchainKHR', 'vkCreateSharedSwapchainsKHR', 'vkGetDeviceGroupSurfacePresentModesKHR', 'vkDebugMarkerSetObjectTagEXT', - 'vkDebugMarkerSetObjectNameEXT'] + 'vkDebugMarkerSetObjectNameEXT', + 'vkSetDebugUtilsObjectNameEXT', + 'vkSetDebugUtilsObjectTagEXT'] ALIASED_CMDS = { 'vkEnumeratePhysicalDeviceGroupsKHR': 'vkEnumeratePhysicalDeviceGroups', @@ -176,7 +187,7 @@ class LoaderExtensionOutputGenerator(OutputGenerator): preamble += '#include "vk_loader_extensions.h"\n' preamble += '#include <vulkan/vk_icd.h>\n' preamble += '#include "wsi.h"\n' - preamble += '#include "debug_report.h"\n' + preamble += '#include "debug_utils.h"\n' preamble += '#include "extension_manual.h"\n' elif self.genOpts.filename == 'vk_layer_dispatch_table.h': @@ -467,7 +478,9 @@ class LoaderExtensionOutputGenerator(OutputGenerator): commands = self.ext_commands for cur_cmd in commands: - if cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice': + is_inst_handle_type = cur_cmd.name in ADD_INST_CMDS or cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice' + if is_inst_handle_type: + if cur_cmd.ext_name != cur_extension_name: if 'VK_VERSION_' in cur_cmd.ext_name: table += '\n // ---- Core %s commands\n' % cur_cmd.ext_name[11:] @@ -506,7 +519,9 @@ class LoaderExtensionOutputGenerator(OutputGenerator): commands = self.ext_commands for cur_cmd in commands: - if cur_cmd.handle_type != 'VkInstance' and cur_cmd.handle_type != 'VkPhysicalDevice': + is_inst_handle_type = cur_cmd.name in ADD_INST_CMDS or cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice' + if not is_inst_handle_type: + if cur_cmd.ext_name != cur_extension_name: if 'VK_VERSION_' in cur_cmd.ext_name: table += '\n // ---- Core %s commands\n' % cur_cmd.ext_name[11:] @@ -545,7 +560,7 @@ class LoaderExtensionOutputGenerator(OutputGenerator): commands = self.ext_commands for cur_cmd in commands: - is_inst_handle_type = cur_cmd.ext_type == 'instance' or cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice' + is_inst_handle_type = cur_cmd.name in ADD_INST_CMDS or cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice' if ((is_inst_handle_type or cur_cmd.name in DEVICE_CMDS_NEED_TERM) and (cur_cmd.name != 'vkGetInstanceProcAddr' and cur_cmd.name != 'vkEnumerateDeviceLayerProperties')): @@ -607,7 +622,7 @@ class LoaderExtensionOutputGenerator(OutputGenerator): required = False for cur_cmd in commands: - is_inst_handle_type = cur_cmd.ext_type == 'instance' or cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice' + is_inst_handle_type = cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice' if ((is_inst_handle_type or cur_cmd.name in DEVICE_CMDS_NEED_TERM) and (cur_cmd.name not in skip_gipa_commands)): if cur_cmd.ext_name != cur_extension_name: @@ -666,7 +681,7 @@ class LoaderExtensionOutputGenerator(OutputGenerator): terminators += '// Loader core instance terminators\n' for cur_cmd in self.core_commands: - is_inst_handle_type = cur_cmd.ext_type == 'instance' or cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice' + is_inst_handle_type = cur_cmd.name in ADD_INST_CMDS or cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice' if is_inst_handle_type: mod_string = '' new_terminator = cur_cmd.cdecl @@ -878,6 +893,7 @@ class LoaderExtensionOutputGenerator(OutputGenerator): for ext_cmd in self.ext_commands: if (ext_cmd.ext_name in WSI_EXT_NAMES or ext_cmd.ext_name in AVOID_EXT_NAMES or + ext_cmd.name in AVOID_CMD_NAMES or ext_cmd.name in manual_ext_commands): continue @@ -937,8 +953,9 @@ class LoaderExtensionOutputGenerator(OutputGenerator): return_prefix += 'return ' has_return_type = True - if (ext_cmd.ext_type == 'instance' or ext_cmd.handle_type == 'VkPhysicalDevice' or - 'DebugMarkerSetObject' in ext_cmd.name or ext_cmd.name in DEVICE_CMDS_NEED_TERM): + if (ext_cmd.handle_type == 'VkInstance' or ext_cmd.handle_type == 'VkPhysicalDevice' or + 'DebugMarkerSetObject' in ext_cmd.name or 'SetDebugUtilsObject' in ext_cmd.name or + ext_cmd.name in DEVICE_CMDS_NEED_TERM): requires_terminator = 1 if requires_terminator == 1: @@ -973,6 +990,22 @@ class LoaderExtensionOutputGenerator(OutputGenerator): funcs += ' struct loader_physical_device_tramp *phys_dev_tramp = (struct loader_physical_device_tramp *)(uintptr_t)pTagInfo->object;\n' funcs += ' local_tag_info.object = (uint64_t)(uintptr_t)phys_dev_tramp->phys_dev;\n' funcs += ' }\n' + elif 'SetDebugUtilsObjectName' in ext_cmd.name: + funcs += ' VkDebugUtilsObjectNameInfoEXT local_name_info;\n' + funcs += ' memcpy(&local_name_info, pNameInfo, sizeof(VkDebugUtilsObjectNameInfoEXT));\n' + funcs += ' // If this is a physical device, we have to replace it with the proper one for the next call.\n' + funcs += ' if (pNameInfo->objectType == VK_OBJECT_TYPE_PHYSICAL_DEVICE) {\n' + funcs += ' struct loader_physical_device_tramp *phys_dev_tramp = (struct loader_physical_device_tramp *)(uintptr_t)pNameInfo->objectHandle;\n' + funcs += ' local_name_info.objectHandle = (uint64_t)(uintptr_t)phys_dev_tramp->phys_dev;\n' + funcs += ' }\n' + elif 'SetDebugUtilsObjectTag' in ext_cmd.name: + funcs += ' VkDebugUtilsObjectTagInfoEXT local_tag_info;\n' + funcs += ' memcpy(&local_tag_info, pTagInfo, sizeof(VkDebugUtilsObjectTagInfoEXT));\n' + funcs += ' // If this is a physical device, we have to replace it with the proper one for the next call.\n' + funcs += ' if (pTagInfo->objectType == VK_OBJECT_TYPE_PHYSICAL_DEVICE) {\n' + funcs += ' struct loader_physical_device_tramp *phys_dev_tramp = (struct loader_physical_device_tramp *)(uintptr_t)pTagInfo->objectHandle;\n' + funcs += ' local_tag_info.objectHandle = (uint64_t)(uintptr_t)phys_dev_tramp->phys_dev;\n' + funcs += ' }\n' funcs += return_prefix funcs += 'disp->' @@ -985,9 +1018,9 @@ class LoaderExtensionOutputGenerator(OutputGenerator): if param.type == 'VkPhysicalDevice': funcs += 'unwrapped_phys_dev' - elif 'DebugMarkerSetObject' in ext_cmd.name and param.name == 'pNameInfo': + elif ('DebugMarkerSetObject' in ext_cmd.name or 'SetDebugUtilsObject' in ext_cmd.name) and param.name == 'pNameInfo': funcs += '&local_name_info' - elif 'DebugMarkerSetObject' in ext_cmd.name and param.name == 'pTagInfo': + elif ('DebugMarkerSetObject' in ext_cmd.name or 'SetDebugUtilsObject' in ext_cmd.name) and param.name == 'pTagInfo': funcs += '&local_tag_info' else: funcs += param.name @@ -1059,7 +1092,7 @@ class LoaderExtensionOutputGenerator(OutputGenerator): count += 1 funcs += ');\n' - elif has_surface == 1 and ext_cmd.ext_type == 'device': + elif has_surface == 1 and not (ext_cmd.handle_type == 'VkPhysicalDevice' or ext_cmd.handle_type == 'VkInstance'): funcs += ' uint32_t icd_index = 0;\n' funcs += ' struct loader_device *dev;\n' funcs += ' struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, &icd_index);\n' @@ -1096,7 +1129,7 @@ class LoaderExtensionOutputGenerator(OutputGenerator): elif ext_cmd.handle_type == 'VkInstance': funcs += '#error("Not implemented. Likely needs to be manually generated!");\n' - elif 'DebugMarkerSetObject' in ext_cmd.name: + elif 'DebugMarkerSetObject' in ext_cmd.name or 'SetDebugUtilsObject' in ext_cmd.name: funcs += ' uint32_t icd_index = 0;\n' funcs += ' struct loader_device *dev;\n' funcs += ' struct loader_icd_term *icd_term = loader_get_icd_and_device(%s, &dev, &icd_index);\n' % (ext_cmd.params[0].name) @@ -1131,6 +1164,45 @@ class LoaderExtensionOutputGenerator(OutputGenerator): funcs += ' if (NULL != icd_surface->real_icd_surfaces) {\n' funcs += ' local_tag_info.object = (uint64_t)icd_surface->real_icd_surfaces[icd_index];\n' funcs += ' }\n' + elif 'SetDebugUtilsObjectName' in ext_cmd.name: + funcs += ' VkDebugUtilsObjectNameInfoEXT local_name_info;\n' + funcs += ' memcpy(&local_name_info, pNameInfo, sizeof(VkDebugUtilsObjectNameInfoEXT));\n' + funcs += ' // If this is a physical device, we have to replace it with the proper one for the next call.\n' + funcs += ' if (pNameInfo->objectType == VK_OBJECT_TYPE_PHYSICAL_DEVICE) {\n' + funcs += ' struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)(uintptr_t)pNameInfo->objectHandle;\n' + funcs += ' local_name_info.objectHandle = (uint64_t)(uintptr_t)phys_dev_term->phys_dev;\n' + funcs += ' // If this is a KHR_surface, and the ICD has created its own, we have to replace it with the proper one for the next call.\n' + funcs += ' } else if (pNameInfo->objectType == VK_OBJECT_TYPE_SURFACE_KHR) {\n' + funcs += ' if (NULL != icd_term && NULL != icd_term->dispatch.CreateSwapchainKHR) {\n' + funcs += ' VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pNameInfo->objectHandle;\n' + funcs += ' if (NULL != icd_surface->real_icd_surfaces) {\n' + funcs += ' local_name_info.objectHandle = (uint64_t)icd_surface->real_icd_surfaces[icd_index];\n' + funcs += ' }\n' + elif 'SetDebugUtilsObjectTag' in ext_cmd.name: + funcs += ' VkDebugUtilsObjectTagInfoEXT local_tag_info;\n' + funcs += ' memcpy(&local_tag_info, pTagInfo, sizeof(VkDebugUtilsObjectTagInfoEXT));\n' + funcs += ' // If this is a physical device, we have to replace it with the proper one for the next call.\n' + funcs += ' if (pTagInfo->objectType == VK_OBJECT_TYPE_PHYSICAL_DEVICE) {\n' + funcs += ' struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)(uintptr_t)pTagInfo->objectHandle;\n' + funcs += ' local_tag_info.objectHandle = (uint64_t)(uintptr_t)phys_dev_term->phys_dev;\n' + funcs += ' // If this is a KHR_surface, and the ICD has created its own, we have to replace it with the proper one for the next call.\n' + funcs += ' } else if (pTagInfo->objectType == VK_OBJECT_TYPE_SURFACE_KHR) {\n' + funcs += ' if (NULL != icd_term && NULL != icd_term->dispatch.CreateSwapchainKHR) {\n' + funcs += ' VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pTagInfo->objectHandle;\n' + funcs += ' if (NULL != icd_surface->real_icd_surfaces) {\n' + funcs += ' local_tag_info.objectHandle = (uint64_t)icd_surface->real_icd_surfaces[icd_index];\n' + funcs += ' }\n' + else: + funcs += ' if (%s->objectType == VK_OBJECT_TYPE_PHYSICAL_DEVICE) {\n' % (ext_cmd.params[1].name) + funcs += ' struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)(uintptr_t)%s->objectHandle;\n' % (ext_cmd.params[1].name) + funcs += ' %s->objectHandle = (uint64_t)(uintptr_t)phys_dev_term->phys_dev;\n' % (ext_cmd.params[1].name) + funcs += ' // If this is a KHR_surface, and the ICD has created its own, we have to replace it with the proper one for the next call.\n' + funcs += ' } else if (%s->objectType == VK_OBJECT_TYPE_SURFACE_KHR) {\n' % (ext_cmd.params[1].name) + funcs += ' if (NULL != icd_term && NULL != icd_term->dispatch.CreateSwapchainKHR) {\n' + funcs += ' VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)%s->objectHandle;\n' % (ext_cmd.params[1].name) + funcs += ' if (NULL != icd_surface->real_icd_surfaces) {\n' + funcs += ' %s->objectHandle = (uint64_t)icd_surface->real_icd_surfaces[icd_index];\n' % (ext_cmd.params[1].name) + funcs += ' }\n' funcs += ' }\n' funcs += ' }\n' funcs += ' return icd_term->dispatch.' @@ -1145,9 +1217,9 @@ class LoaderExtensionOutputGenerator(OutputGenerator): funcs += 'phys_dev_term->phys_dev' elif param.type == 'VkSurfaceKHR': funcs += 'icd_surface->real_icd_surfaces[icd_index]' - elif 'DebugMarkerSetObject' in ext_cmd.name and param.name == 'pNameInfo': + elif ('DebugMarkerSetObject' in ext_cmd.name or 'SetDebugUtilsObject' in ext_cmd.name) and param.name == 'pNameInfo': funcs += '&local_name_info' - elif 'DebugMarkerSetObject' in ext_cmd.name and param.name == 'pTagInfo': + elif ('DebugMarkerSetObject' in ext_cmd.name or 'SetDebugUtilsObject' in ext_cmd.name) and param.name == 'pTagInfo': funcs += '&local_tag_info' else: funcs += param.name @@ -1202,7 +1274,8 @@ class LoaderExtensionOutputGenerator(OutputGenerator): for cur_cmd in self.ext_commands: if ('VK_VERSION_' in cur_cmd.ext_name or cur_cmd.ext_name in WSI_EXT_NAMES or - cur_cmd.ext_name in AVOID_EXT_NAMES): + cur_cmd.ext_name in AVOID_EXT_NAMES or + cur_cmd.name in AVOID_CMD_NAMES ): continue if cur_cmd.ext_name != cur_extension_name: @@ -1252,8 +1325,8 @@ class LoaderExtensionOutputGenerator(OutputGenerator): create_func += ' for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {\n' for ext in entries: if ('VK_VERSION_' in ext.name or ext.name in WSI_EXT_NAMES or - ext.name in AVOID_EXT_NAMES or ext.type == 'device' or - ext.num_commands == 0): + ext.name in AVOID_EXT_NAMES or ext.name in AVOID_CMD_NAMES or + ext.type == 'device' or ext.num_commands == 0): continue if ext.name != cur_extension_name: diff --git a/scripts/object_tracker_generator.py b/scripts/object_tracker_generator.py index 405a5b7c..26c1105a 100644 --- a/scripts/object_tracker_generator.py +++ b/scripts/object_tracker_generator.py @@ -172,6 +172,17 @@ class ObjectTrackerOutputGenerator(OutputGenerator): 'vkGetDeviceQueue', 'vkGetSwapchainImagesKHR', 'vkCreateDescriptorSetLayout', + 'vkCreateDebugUtilsMessengerEXT', + 'vkDestroyDebugUtilsMessengerEXT', + 'vkSubmitDebugUtilsMessageEXT', + 'vkSetDebugUtilsObjectNameEXT', + 'vkSetDebugUtilsObjectTagEXT', + 'vkQueueBeginDebugUtilsLabelEXT', + 'vkQueueEndDebugUtilsLabelEXT', + 'vkQueueInsertDebugUtilsLabelEXT', + 'vkCmdBeginDebugUtilsLabelEXT', + 'vkCmdEndDebugUtilsLabelEXT', + 'vkCmdInsertDebugUtilsLabelEXT', ] # These VUIDS are not implicit, but are best handled in this layer. Codegen for vkDestroy calls will generate a key # which is translated here into a good VU. Saves ~40 checks. diff --git a/scripts/parameter_validation_generator.py b/scripts/parameter_validation_generator.py index edd49b55..4246eeae 100644 --- a/scripts/parameter_validation_generator.py +++ b/scripts/parameter_validation_generator.py @@ -127,17 +127,12 @@ class ParameterValidationOutputGenerator(OutputGenerator): self.blacklist = [ 'vkGetInstanceProcAddr', 'vkGetDeviceProcAddr', - 'vkEnumerateInstanceLayerProperties', - 'vkEnumerateInstanceExtensionsProperties', - 'vkEnumerateDeviceLayerProperties', - 'vkEnumerateDeviceExtensionsProperties', - 'vkCreateDebugReportCallbackKHR', - 'vkDestroyDebugReportCallbackKHR', + 'vkEnumerateInstanceVersion', 'vkEnumerateInstanceLayerProperties', 'vkEnumerateInstanceExtensionProperties', 'vkEnumerateDeviceLayerProperties', - 'vkCmdDebugMarkerEndEXT', 'vkEnumerateDeviceExtensionProperties', + 'vkCmdDebugMarkerEndEXT', ] self.validate_only = [ 'vkCreateInstance', @@ -150,6 +145,8 @@ class ParameterValidationOutputGenerator(OutputGenerator): 'vkCreateCommandPool', 'vkCreateRenderPass', 'vkDestroyRenderPass', + 'vkCreateDebugUtilsMessengerEXT', + 'vkDestroyDebugUtilsMessengerEXT', ] # Structure fields to ignore self.structMemberBlacklist = { 'VkWriteDescriptorSet' : ['dstSet'] } diff --git a/scripts/threading_generator.py b/scripts/threading_generator.py index fd88909c..4ac65d67 100644 --- a/scripts/threading_generator.py +++ b/scripts/threading_generator.py @@ -384,6 +384,8 @@ class ThreadOutputGenerator(OutputGenerator): 'vkEnumerateInstanceExtensionProperties', 'vkEnumerateDeviceLayerProperties', 'vkEnumerateDeviceExtensionProperties', + 'vkCreateDebugUtilsMessengerEXT', + 'vkDestroyDebugUtilsMessengerEXT', ] if name in special_functions: decls = self.makeCDecls(cmdinfo.elem) @@ -392,7 +394,7 @@ class ThreadOutputGenerator(OutputGenerator): self.appendSection('command', decls[0]) self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ] return - if "QueuePresentKHR" in name or ("DebugMarker" in name and "EXT" in name): + if "QueuePresentKHR" in name or (("DebugMarker" in name or "DebugUtilsObject" in name) and "EXT" in name): self.appendSection('command', '// TODO - not wrapping EXT function ' + name) return # Determine first if this function needs to be intercepted diff --git a/scripts/unique_objects_generator.py b/scripts/unique_objects_generator.py index 78526a3e..289a5bbe 100644 --- a/scripts/unique_objects_generator.py +++ b/scripts/unique_objects_generator.py @@ -157,6 +157,8 @@ class UniqueObjectsOutputGenerator(OutputGenerator): 'vkGetDisplayModeProperties2KHR', 'vkCreateRenderPass', 'vkDestroyRenderPass', + 'vkSetDebugUtilsObjectNameEXT', + 'vkSetDebugUtilsObjectTagEXT', ] # Commands shadowed by interface functions and are not implemented self.interface_functions = [ @@ -165,10 +167,14 @@ class UniqueObjectsOutputGenerator(OutputGenerator): 'vkGetDisplayPlaneSupportedDisplaysKHR', 'vkGetDisplayModePropertiesKHR', 'vkGetDisplayPlaneCapabilitiesKHR', - # DebugReport APIs are hooked, but handled separately in the source file + # VK_EXT_debug_report APIs are hooked, but handled separately in the source file 'vkCreateDebugReportCallbackEXT', 'vkDestroyDebugReportCallbackEXT', 'vkDebugReportMessageEXT', + # VK_EXT_debug_utils APIs are hooked, but handled separately in the source file + 'vkCreateDebugUtilsMessengerEXT', + 'vkDestroyDebugUtilsMessengerEXT', + 'vkSubmitDebugUtilsMessageEXT', ] self.headerVersion = None # Internal state - accumulators for different inner block text diff --git a/scripts/vuid_mapping.py b/scripts/vuid_mapping.py index e3dbfdf9..88df867a 100644 --- a/scripts/vuid_mapping.py +++ b/scripts/vuid_mapping.py @@ -1104,7 +1104,7 @@ uniqueid_set = set() # store uniqueid to make sure we don't have duplicates # Convert a string VUID into numerical value # See "VUID Mapping Details" comment above for more info def convertVUID(vuid_string): - """Convert a string-based VUID into a numberical value""" + """Convert a string-based VUID into a numerical value""" #func_struct_update = False #imp_param_update = False if vuid_string in ['', None]: |
