1/* 2 * Copyright © 2021 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 */ 23 24#include "vk_debug_utils.h" 25 26#include "vk_common_entrypoints.h" 27#include "vk_command_buffer.h" 28#include "vk_device.h" 29#include "vk_queue.h" 30#include "vk_object.h" 31#include "vk_alloc.h" 32#include "vk_util.h" 33#include "stdarg.h" 34#include "u_dynarray.h" 35 36void 37vk_debug_message(struct vk_instance *instance, 38 VkDebugUtilsMessageSeverityFlagBitsEXT severity, 39 VkDebugUtilsMessageTypeFlagsEXT types, 40 const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData) 41{ 42 mtx_lock(&instance->debug_utils.callbacks_mutex); 43 44 list_for_each_entry(struct vk_debug_utils_messenger, messenger, 45 &instance->debug_utils.callbacks, link) { 46 if ((messenger->severity & severity) && 47 (messenger->type & types)) 48 messenger->callback(severity, types, pCallbackData, messenger->data); 49 } 50 51 mtx_unlock(&instance->debug_utils.callbacks_mutex); 52} 53 54/* This function intended to be used by the drivers to report a 55 * message to the special messenger, provided in the pNext chain while 56 * creating an instance. It's only meant to be used during 57 * vkCreateInstance or vkDestroyInstance calls. 58 */ 59void 60vk_debug_message_instance(struct vk_instance *instance, 61 VkDebugUtilsMessageSeverityFlagBitsEXT severity, 62 VkDebugUtilsMessageTypeFlagsEXT types, 63 const char *pMessageIdName, 64 int32_t messageIdNumber, 65 const char *pMessage) 66{ 67 if (list_is_empty(&instance->debug_utils.instance_callbacks)) 68 return; 69 70 const VkDebugUtilsMessengerCallbackDataEXT cbData = { 71 .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT, 72 .pMessageIdName = pMessageIdName, 73 .messageIdNumber = messageIdNumber, 74 .pMessage = pMessage, 75 }; 76 77 list_for_each_entry(struct vk_debug_utils_messenger, messenger, 78 &instance->debug_utils.instance_callbacks, link) { 79 if ((messenger->severity & severity) && 80 (messenger->type & types)) 81 messenger->callback(severity, types, &cbData, messenger->data); 82 } 83} 84 85VKAPI_ATTR VkResult VKAPI_CALL 86vk_common_CreateDebugUtilsMessengerEXT( 87 VkInstance _instance, 88 const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo, 89 const VkAllocationCallbacks *pAllocator, 90 VkDebugUtilsMessengerEXT *pMessenger) 91{ 92 VK_FROM_HANDLE(vk_instance, instance, _instance); 93 94 struct vk_debug_utils_messenger *messenger = 95 vk_alloc2(&instance->alloc, pAllocator, 96 sizeof(struct vk_debug_utils_messenger), 8, 97 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 98 99 if (!messenger) 100 return VK_ERROR_OUT_OF_HOST_MEMORY; 101 102 if (pAllocator) 103 messenger->alloc = *pAllocator; 104 else 105 messenger->alloc = instance->alloc; 106 107 vk_object_base_init(NULL, &messenger->base, 108 VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT); 109 110 messenger->severity = pCreateInfo->messageSeverity; 111 messenger->type = pCreateInfo->messageType; 112 messenger->callback = pCreateInfo->pfnUserCallback; 113 messenger->data = pCreateInfo->pUserData; 114 115 mtx_lock(&instance->debug_utils.callbacks_mutex); 116 list_addtail(&messenger->link, &instance->debug_utils.callbacks); 117 mtx_unlock(&instance->debug_utils.callbacks_mutex); 118 119 *pMessenger = vk_debug_utils_messenger_to_handle(messenger); 120 121 return VK_SUCCESS; 122} 123 124VKAPI_ATTR void VKAPI_CALL 125vk_common_SubmitDebugUtilsMessageEXT( 126 VkInstance _instance, 127 VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, 128 VkDebugUtilsMessageTypeFlagsEXT messageTypes, 129 const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData) 130{ 131 VK_FROM_HANDLE(vk_instance, instance, _instance); 132 133 vk_debug_message(instance, messageSeverity, messageTypes, pCallbackData); 134} 135 136VKAPI_ATTR void VKAPI_CALL 137vk_common_DestroyDebugUtilsMessengerEXT( 138 VkInstance _instance, 139 VkDebugUtilsMessengerEXT _messenger, 140 const VkAllocationCallbacks *pAllocator) 141{ 142 VK_FROM_HANDLE(vk_instance, instance, _instance); 143 VK_FROM_HANDLE(vk_debug_utils_messenger, messenger, _messenger); 144 145 if (messenger == NULL) 146 return; 147 148 mtx_lock(&instance->debug_utils.callbacks_mutex); 149 list_del(&messenger->link); 150 mtx_unlock(&instance->debug_utils.callbacks_mutex); 151 152 vk_object_base_finish(&messenger->base); 153 vk_free2(&instance->alloc, pAllocator, messenger); 154} 155 156VKAPI_ATTR VkResult VKAPI_CALL 157vk_common_SetDebugUtilsObjectNameEXT( 158 VkDevice _device, 159 const VkDebugUtilsObjectNameInfoEXT *pNameInfo) 160{ 161 VK_FROM_HANDLE(vk_device, device, _device); 162 struct vk_object_base *object = 163 vk_object_base_from_u64_handle(pNameInfo->objectHandle, 164 pNameInfo->objectType); 165 166 if (object->object_name) { 167 vk_free(&device->alloc, object->object_name); 168 object->object_name = NULL; 169 } 170 object->object_name = vk_strdup(&device->alloc, pNameInfo->pObjectName, 171 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 172 if (!object->object_name) 173 return VK_ERROR_OUT_OF_HOST_MEMORY; 174 175 return VK_SUCCESS; 176} 177 178VKAPI_ATTR VkResult VKAPI_CALL 179vk_common_SetDebugUtilsObjectTagEXT( 180 VkDevice _device, 181 const VkDebugUtilsObjectTagInfoEXT *pTagInfo) 182{ 183 /* no-op */ 184 return VK_SUCCESS; 185} 186 187VKAPI_ATTR void VKAPI_CALL 188vk_common_CmdBeginDebugUtilsLabelEXT( 189 VkCommandBuffer _commandBuffer, 190 const VkDebugUtilsLabelEXT *pLabelInfo) 191{ 192 VK_FROM_HANDLE(vk_command_buffer, command_buffer, _commandBuffer); 193 194 /* If the latest label was submitted by CmdInsertDebugUtilsLabelEXT, we 195 * should remove it first. 196 */ 197 if (!command_buffer->region_begin) 198 (void)util_dynarray_pop(&command_buffer->labels, VkDebugUtilsLabelEXT); 199 200 util_dynarray_append(&command_buffer->labels, VkDebugUtilsLabelEXT, 201 *pLabelInfo); 202 command_buffer->region_begin = true; 203} 204 205VKAPI_ATTR void VKAPI_CALL 206vk_common_CmdEndDebugUtilsLabelEXT(VkCommandBuffer _commandBuffer) 207{ 208 VK_FROM_HANDLE(vk_command_buffer, command_buffer, _commandBuffer); 209 210 /* If the latest label was submitted by CmdInsertDebugUtilsLabelEXT, we 211 * should remove it first. 212 */ 213 if (!command_buffer->region_begin) 214 (void)util_dynarray_pop(&command_buffer->labels, VkDebugUtilsLabelEXT); 215 216 (void)util_dynarray_pop(&command_buffer->labels, VkDebugUtilsLabelEXT); 217 command_buffer->region_begin = true; 218} 219 220VKAPI_ATTR void VKAPI_CALL 221vk_common_CmdInsertDebugUtilsLabelEXT( 222 VkCommandBuffer _commandBuffer, 223 const VkDebugUtilsLabelEXT *pLabelInfo) 224{ 225 VK_FROM_HANDLE(vk_command_buffer, command_buffer, _commandBuffer); 226 227 /* If the latest label was submitted by CmdInsertDebugUtilsLabelEXT, we 228 * should remove it first. 229 */ 230 if (!command_buffer->region_begin) 231 (void)util_dynarray_pop(&command_buffer->labels, VkDebugUtilsLabelEXT); 232 233 util_dynarray_append(&command_buffer->labels, VkDebugUtilsLabelEXT, 234 *pLabelInfo); 235 command_buffer->region_begin = false; 236} 237 238VKAPI_ATTR void VKAPI_CALL 239vk_common_QueueBeginDebugUtilsLabelEXT( 240 VkQueue _queue, 241 const VkDebugUtilsLabelEXT *pLabelInfo) 242{ 243 VK_FROM_HANDLE(vk_queue, queue, _queue); 244 245 /* If the latest label was submitted by QueueInsertDebugUtilsLabelEXT, we 246 * should remove it first. 247 */ 248 if (!queue->region_begin) 249 (void)util_dynarray_pop(&queue->labels, VkDebugUtilsLabelEXT); 250 251 util_dynarray_append(&queue->labels, VkDebugUtilsLabelEXT, *pLabelInfo); 252 queue->region_begin = true; 253} 254 255VKAPI_ATTR void VKAPI_CALL 256vk_common_QueueEndDebugUtilsLabelEXT(VkQueue _queue) 257{ 258 VK_FROM_HANDLE(vk_queue, queue, _queue); 259 260 /* If the latest label was submitted by QueueInsertDebugUtilsLabelEXT, we 261 * should remove it first. 262 */ 263 if (!queue->region_begin) 264 (void)util_dynarray_pop(&queue->labels, VkDebugUtilsLabelEXT); 265 266 (void)util_dynarray_pop(&queue->labels, VkDebugUtilsLabelEXT); 267 queue->region_begin = true; 268} 269 270VKAPI_ATTR void VKAPI_CALL 271vk_common_QueueInsertDebugUtilsLabelEXT( 272 VkQueue _queue, 273 const VkDebugUtilsLabelEXT *pLabelInfo) 274{ 275 VK_FROM_HANDLE(vk_queue, queue, _queue); 276 277 /* If the latest label was submitted by QueueInsertDebugUtilsLabelEXT, we 278 * should remove it first. 279 */ 280 if (!queue->region_begin) 281 (void)util_dynarray_pop(&queue->labels, VkDebugUtilsLabelEXT); 282 283 util_dynarray_append(&queue->labels, VkDebugUtilsLabelEXT, *pLabelInfo); 284 queue->region_begin = false; 285} 286