| /* |
| * Copyright © 2021 Intel Corporation |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the "Software"), |
| * to deal in the Software without restriction, including without limitation |
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| * and/or sell copies of the Software, and to permit persons to whom the |
| * Software is furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice (including the next |
| * paragraph) shall be included in all copies or substantial portions of the |
| * Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
| * IN THE SOFTWARE. |
| */ |
| |
| #include "vk_debug_utils.h" |
| |
| #include "vk_common_entrypoints.h" |
| #include "vk_command_buffer.h" |
| #include "vk_device.h" |
| #include "vk_queue.h" |
| #include "vk_object.h" |
| #include "vk_alloc.h" |
| #include "vk_util.h" |
| #include "stdarg.h" |
| #include "u_dynarray.h" |
| |
| void |
| vk_debug_message(struct vk_instance *instance, |
| VkDebugUtilsMessageSeverityFlagBitsEXT severity, |
| VkDebugUtilsMessageTypeFlagsEXT types, |
| const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData) |
| { |
| mtx_lock(&instance->debug_utils.callbacks_mutex); |
| |
| list_for_each_entry(struct vk_debug_utils_messenger, messenger, |
| &instance->debug_utils.callbacks, link) { |
| if ((messenger->severity & severity) && |
| (messenger->type & types)) |
| messenger->callback(severity, types, pCallbackData, messenger->data); |
| } |
| |
| mtx_unlock(&instance->debug_utils.callbacks_mutex); |
| } |
| |
| /* This function intended to be used by the drivers to report a |
| * message to the special messenger, provided in the pNext chain while |
| * creating an instance. It's only meant to be used during |
| * vkCreateInstance or vkDestroyInstance calls. |
| */ |
| void |
| vk_debug_message_instance(struct vk_instance *instance, |
| VkDebugUtilsMessageSeverityFlagBitsEXT severity, |
| VkDebugUtilsMessageTypeFlagsEXT types, |
| const char *pMessageIdName, |
| int32_t messageIdNumber, |
| const char *pMessage) |
| { |
| if (list_is_empty(&instance->debug_utils.instance_callbacks)) |
| return; |
| |
| const VkDebugUtilsMessengerCallbackDataEXT cbData = { |
| .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT, |
| .pMessageIdName = pMessageIdName, |
| .messageIdNumber = messageIdNumber, |
| .pMessage = pMessage, |
| }; |
| |
| list_for_each_entry(struct vk_debug_utils_messenger, messenger, |
| &instance->debug_utils.instance_callbacks, link) { |
| if ((messenger->severity & severity) && |
| (messenger->type & types)) |
| messenger->callback(severity, types, &cbData, messenger->data); |
| } |
| } |
| |
| VKAPI_ATTR VkResult VKAPI_CALL |
| vk_common_CreateDebugUtilsMessengerEXT( |
| VkInstance _instance, |
| const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo, |
| const VkAllocationCallbacks *pAllocator, |
| VkDebugUtilsMessengerEXT *pMessenger) |
| { |
| VK_FROM_HANDLE(vk_instance, instance, _instance); |
| |
| struct vk_debug_utils_messenger *messenger = |
| vk_alloc2(&instance->alloc, pAllocator, |
| sizeof(struct vk_debug_utils_messenger), 8, |
| VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); |
| |
| if (!messenger) |
| return VK_ERROR_OUT_OF_HOST_MEMORY; |
| |
| if (pAllocator) |
| messenger->alloc = *pAllocator; |
| else |
| messenger->alloc = instance->alloc; |
| |
| vk_object_base_init(NULL, &messenger->base, |
| VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT); |
| |
| messenger->severity = pCreateInfo->messageSeverity; |
| messenger->type = pCreateInfo->messageType; |
| messenger->callback = pCreateInfo->pfnUserCallback; |
| messenger->data = pCreateInfo->pUserData; |
| |
| mtx_lock(&instance->debug_utils.callbacks_mutex); |
| list_addtail(&messenger->link, &instance->debug_utils.callbacks); |
| mtx_unlock(&instance->debug_utils.callbacks_mutex); |
| |
| *pMessenger = vk_debug_utils_messenger_to_handle(messenger); |
| |
| return VK_SUCCESS; |
| } |
| |
| VKAPI_ATTR void VKAPI_CALL |
| vk_common_SubmitDebugUtilsMessageEXT( |
| VkInstance _instance, |
| VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, |
| VkDebugUtilsMessageTypeFlagsEXT messageTypes, |
| const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData) |
| { |
| VK_FROM_HANDLE(vk_instance, instance, _instance); |
| |
| vk_debug_message(instance, messageSeverity, messageTypes, pCallbackData); |
| } |
| |
| VKAPI_ATTR void VKAPI_CALL |
| vk_common_DestroyDebugUtilsMessengerEXT( |
| VkInstance _instance, |
| VkDebugUtilsMessengerEXT _messenger, |
| const VkAllocationCallbacks *pAllocator) |
| { |
| VK_FROM_HANDLE(vk_instance, instance, _instance); |
| VK_FROM_HANDLE(vk_debug_utils_messenger, messenger, _messenger); |
| |
| if (messenger == NULL) |
| return; |
| |
| mtx_lock(&instance->debug_utils.callbacks_mutex); |
| list_del(&messenger->link); |
| mtx_unlock(&instance->debug_utils.callbacks_mutex); |
| |
| vk_object_base_finish(&messenger->base); |
| vk_free2(&instance->alloc, pAllocator, messenger); |
| } |
| |
| VKAPI_ATTR VkResult VKAPI_CALL |
| vk_common_SetDebugUtilsObjectNameEXT( |
| VkDevice _device, |
| const VkDebugUtilsObjectNameInfoEXT *pNameInfo) |
| { |
| VK_FROM_HANDLE(vk_device, device, _device); |
| struct vk_object_base *object = |
| vk_object_base_from_u64_handle(pNameInfo->objectHandle, |
| pNameInfo->objectType); |
| |
| if (object->object_name) { |
| vk_free(&device->alloc, object->object_name); |
| object->object_name = NULL; |
| } |
| object->object_name = vk_strdup(&device->alloc, pNameInfo->pObjectName, |
| VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); |
| if (!object->object_name) |
| return VK_ERROR_OUT_OF_HOST_MEMORY; |
| |
| return VK_SUCCESS; |
| } |
| |
| VKAPI_ATTR VkResult VKAPI_CALL |
| vk_common_SetDebugUtilsObjectTagEXT( |
| VkDevice _device, |
| const VkDebugUtilsObjectTagInfoEXT *pTagInfo) |
| { |
| /* no-op */ |
| return VK_SUCCESS; |
| } |
| |
| VKAPI_ATTR void VKAPI_CALL |
| vk_common_CmdBeginDebugUtilsLabelEXT( |
| VkCommandBuffer _commandBuffer, |
| const VkDebugUtilsLabelEXT *pLabelInfo) |
| { |
| VK_FROM_HANDLE(vk_command_buffer, command_buffer, _commandBuffer); |
| |
| /* If the latest label was submitted by CmdInsertDebugUtilsLabelEXT, we |
| * should remove it first. |
| */ |
| if (!command_buffer->region_begin) |
| (void)util_dynarray_pop(&command_buffer->labels, VkDebugUtilsLabelEXT); |
| |
| util_dynarray_append(&command_buffer->labels, VkDebugUtilsLabelEXT, |
| *pLabelInfo); |
| command_buffer->region_begin = true; |
| } |
| |
| VKAPI_ATTR void VKAPI_CALL |
| vk_common_CmdEndDebugUtilsLabelEXT(VkCommandBuffer _commandBuffer) |
| { |
| VK_FROM_HANDLE(vk_command_buffer, command_buffer, _commandBuffer); |
| |
| /* If the latest label was submitted by CmdInsertDebugUtilsLabelEXT, we |
| * should remove it first. |
| */ |
| if (!command_buffer->region_begin) |
| (void)util_dynarray_pop(&command_buffer->labels, VkDebugUtilsLabelEXT); |
| |
| (void)util_dynarray_pop(&command_buffer->labels, VkDebugUtilsLabelEXT); |
| command_buffer->region_begin = true; |
| } |
| |
| VKAPI_ATTR void VKAPI_CALL |
| vk_common_CmdInsertDebugUtilsLabelEXT( |
| VkCommandBuffer _commandBuffer, |
| const VkDebugUtilsLabelEXT *pLabelInfo) |
| { |
| VK_FROM_HANDLE(vk_command_buffer, command_buffer, _commandBuffer); |
| |
| /* If the latest label was submitted by CmdInsertDebugUtilsLabelEXT, we |
| * should remove it first. |
| */ |
| if (!command_buffer->region_begin) |
| (void)util_dynarray_pop(&command_buffer->labels, VkDebugUtilsLabelEXT); |
| |
| util_dynarray_append(&command_buffer->labels, VkDebugUtilsLabelEXT, |
| *pLabelInfo); |
| command_buffer->region_begin = false; |
| } |
| |
| VKAPI_ATTR void VKAPI_CALL |
| vk_common_QueueBeginDebugUtilsLabelEXT( |
| VkQueue _queue, |
| const VkDebugUtilsLabelEXT *pLabelInfo) |
| { |
| VK_FROM_HANDLE(vk_queue, queue, _queue); |
| |
| /* If the latest label was submitted by QueueInsertDebugUtilsLabelEXT, we |
| * should remove it first. |
| */ |
| if (!queue->region_begin) |
| (void)util_dynarray_pop(&queue->labels, VkDebugUtilsLabelEXT); |
| |
| util_dynarray_append(&queue->labels, VkDebugUtilsLabelEXT, *pLabelInfo); |
| queue->region_begin = true; |
| } |
| |
| VKAPI_ATTR void VKAPI_CALL |
| vk_common_QueueEndDebugUtilsLabelEXT(VkQueue _queue) |
| { |
| VK_FROM_HANDLE(vk_queue, queue, _queue); |
| |
| /* If the latest label was submitted by QueueInsertDebugUtilsLabelEXT, we |
| * should remove it first. |
| */ |
| if (!queue->region_begin) |
| (void)util_dynarray_pop(&queue->labels, VkDebugUtilsLabelEXT); |
| |
| (void)util_dynarray_pop(&queue->labels, VkDebugUtilsLabelEXT); |
| queue->region_begin = true; |
| } |
| |
| VKAPI_ATTR void VKAPI_CALL |
| vk_common_QueueInsertDebugUtilsLabelEXT( |
| VkQueue _queue, |
| const VkDebugUtilsLabelEXT *pLabelInfo) |
| { |
| VK_FROM_HANDLE(vk_queue, queue, _queue); |
| |
| /* If the latest label was submitted by QueueInsertDebugUtilsLabelEXT, we |
| * should remove it first. |
| */ |
| if (!queue->region_begin) |
| (void)util_dynarray_pop(&queue->labels, VkDebugUtilsLabelEXT); |
| |
| util_dynarray_append(&queue->labels, VkDebugUtilsLabelEXT, *pLabelInfo); |
| queue->region_begin = false; |
| } |