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 "util/u_dynarray.h"
35
36 void
vk_debug_message(struct vk_instance * instance,VkDebugUtilsMessageSeverityFlagBitsEXT severity,VkDebugUtilsMessageTypeFlagsEXT types,const VkDebugUtilsMessengerCallbackDataEXT * pCallbackData)37 vk_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 */
59 void
vk_debug_message_instance(struct vk_instance * instance,VkDebugUtilsMessageSeverityFlagBitsEXT severity,VkDebugUtilsMessageTypeFlagsEXT types,const char * pMessageIdName,int32_t messageIdNumber,const char * pMessage)60 vk_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
85 VKAPI_ATTR VkResult VKAPI_CALL
vk_common_CreateDebugUtilsMessengerEXT(VkInstance _instance,const VkDebugUtilsMessengerCreateInfoEXT * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDebugUtilsMessengerEXT * pMessenger)86 vk_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
124 VKAPI_ATTR void VKAPI_CALL
vk_common_SubmitDebugUtilsMessageEXT(VkInstance _instance,VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,VkDebugUtilsMessageTypeFlagsEXT messageTypes,const VkDebugUtilsMessengerCallbackDataEXT * pCallbackData)125 vk_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
136 VKAPI_ATTR void VKAPI_CALL
vk_common_DestroyDebugUtilsMessengerEXT(VkInstance _instance,VkDebugUtilsMessengerEXT _messenger,const VkAllocationCallbacks * pAllocator)137 vk_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
156 VKAPI_ATTR VkResult VKAPI_CALL
vk_common_SetDebugUtilsObjectNameEXT(VkDevice _device,const VkDebugUtilsObjectNameInfoEXT * pNameInfo)157 vk_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
178 VKAPI_ATTR VkResult VKAPI_CALL
vk_common_SetDebugUtilsObjectTagEXT(VkDevice _device,const VkDebugUtilsObjectTagInfoEXT * pTagInfo)179 vk_common_SetDebugUtilsObjectTagEXT(
180 VkDevice _device,
181 const VkDebugUtilsObjectTagInfoEXT *pTagInfo)
182 {
183 /* no-op */
184 return VK_SUCCESS;
185 }
186
187 static void
vk_common_append_debug_label(struct vk_device * device,struct util_dynarray * labels,const VkDebugUtilsLabelEXT * pLabelInfo)188 vk_common_append_debug_label(struct vk_device *device,
189 struct util_dynarray *labels,
190 const VkDebugUtilsLabelEXT *pLabelInfo)
191 {
192 util_dynarray_append(labels, VkDebugUtilsLabelEXT, *pLabelInfo);
193 VkDebugUtilsLabelEXT *current_label =
194 util_dynarray_top_ptr(labels, VkDebugUtilsLabelEXT);
195 current_label->pLabelName =
196 vk_strdup(&device->alloc, current_label->pLabelName,
197 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
198 }
199
200 static void
vk_common_pop_debug_label(struct vk_device * device,struct util_dynarray * labels)201 vk_common_pop_debug_label(struct vk_device *device,
202 struct util_dynarray *labels)
203 {
204 if (labels->size == 0)
205 return;
206
207 VkDebugUtilsLabelEXT previous_label =
208 util_dynarray_pop(labels, VkDebugUtilsLabelEXT);
209 vk_free(&device->alloc, (void *)previous_label.pLabelName);
210 }
211
212 VKAPI_ATTR void VKAPI_CALL
vk_common_CmdBeginDebugUtilsLabelEXT(VkCommandBuffer _commandBuffer,const VkDebugUtilsLabelEXT * pLabelInfo)213 vk_common_CmdBeginDebugUtilsLabelEXT(
214 VkCommandBuffer _commandBuffer,
215 const VkDebugUtilsLabelEXT *pLabelInfo)
216 {
217 VK_FROM_HANDLE(vk_command_buffer, command_buffer, _commandBuffer);
218
219 /* If the latest label was submitted by CmdInsertDebugUtilsLabelEXT, we
220 * should remove it first.
221 */
222 if (!command_buffer->region_begin) {
223 vk_common_pop_debug_label(command_buffer->base.device,
224 &command_buffer->labels);
225 }
226
227 vk_common_append_debug_label(command_buffer->base.device,
228 &command_buffer->labels,
229 pLabelInfo);
230 command_buffer->region_begin = true;
231 }
232
233 VKAPI_ATTR void VKAPI_CALL
vk_common_CmdEndDebugUtilsLabelEXT(VkCommandBuffer _commandBuffer)234 vk_common_CmdEndDebugUtilsLabelEXT(VkCommandBuffer _commandBuffer)
235 {
236 VK_FROM_HANDLE(vk_command_buffer, command_buffer, _commandBuffer);
237
238 /* If the latest label was submitted by CmdInsertDebugUtilsLabelEXT, we
239 * should remove it first.
240 */
241 if (!command_buffer->region_begin) {
242 vk_common_pop_debug_label(command_buffer->base.device,
243 &command_buffer->labels);
244 }
245
246 vk_common_pop_debug_label(command_buffer->base.device,
247 &command_buffer->labels);
248 command_buffer->region_begin = true;
249 }
250
251 VKAPI_ATTR void VKAPI_CALL
vk_common_CmdInsertDebugUtilsLabelEXT(VkCommandBuffer _commandBuffer,const VkDebugUtilsLabelEXT * pLabelInfo)252 vk_common_CmdInsertDebugUtilsLabelEXT(
253 VkCommandBuffer _commandBuffer,
254 const VkDebugUtilsLabelEXT *pLabelInfo)
255 {
256 VK_FROM_HANDLE(vk_command_buffer, command_buffer, _commandBuffer);
257
258 /* If the latest label was submitted by CmdInsertDebugUtilsLabelEXT, we
259 * should remove it first.
260 */
261 if (!command_buffer->region_begin) {
262 vk_common_append_debug_label(command_buffer->base.device,
263 &command_buffer->labels,
264 pLabelInfo);
265 }
266
267 vk_common_append_debug_label(command_buffer->base.device,
268 &command_buffer->labels,
269 pLabelInfo);
270 command_buffer->region_begin = false;
271 }
272
273 VKAPI_ATTR void VKAPI_CALL
vk_common_QueueBeginDebugUtilsLabelEXT(VkQueue _queue,const VkDebugUtilsLabelEXT * pLabelInfo)274 vk_common_QueueBeginDebugUtilsLabelEXT(
275 VkQueue _queue,
276 const VkDebugUtilsLabelEXT *pLabelInfo)
277 {
278 VK_FROM_HANDLE(vk_queue, queue, _queue);
279
280 /* If the latest label was submitted by QueueInsertDebugUtilsLabelEXT, we
281 * should remove it first.
282 */
283 if (!queue->region_begin)
284 (void)util_dynarray_pop(&queue->labels, VkDebugUtilsLabelEXT);
285
286 vk_common_append_debug_label(queue->base.device,
287 &queue->labels,
288 pLabelInfo);
289 queue->region_begin = true;
290 }
291
292 VKAPI_ATTR void VKAPI_CALL
vk_common_QueueEndDebugUtilsLabelEXT(VkQueue _queue)293 vk_common_QueueEndDebugUtilsLabelEXT(VkQueue _queue)
294 {
295 VK_FROM_HANDLE(vk_queue, queue, _queue);
296
297 /* If the latest label was submitted by QueueInsertDebugUtilsLabelEXT, we
298 * should remove it first.
299 */
300 if (!queue->region_begin)
301 vk_common_pop_debug_label(queue->base.device, &queue->labels);
302
303 vk_common_pop_debug_label(queue->base.device, &queue->labels);
304 queue->region_begin = true;
305 }
306
307 VKAPI_ATTR void VKAPI_CALL
vk_common_QueueInsertDebugUtilsLabelEXT(VkQueue _queue,const VkDebugUtilsLabelEXT * pLabelInfo)308 vk_common_QueueInsertDebugUtilsLabelEXT(
309 VkQueue _queue,
310 const VkDebugUtilsLabelEXT *pLabelInfo)
311 {
312 VK_FROM_HANDLE(vk_queue, queue, _queue);
313
314 /* If the latest label was submitted by QueueInsertDebugUtilsLabelEXT, we
315 * should remove it first.
316 */
317 if (!queue->region_begin)
318 vk_common_pop_debug_label(queue->base.device, &queue->labels);
319
320 vk_common_append_debug_label(queue->base.device,
321 &queue->labels,
322 pLabelInfo);
323 queue->region_begin = false;
324 }
325