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 void
vk_address_binding_report(struct vk_instance * instance,struct vk_object_base * object,uint64_t base_address,uint64_t size,VkDeviceAddressBindingTypeEXT type)86 vk_address_binding_report(struct vk_instance *instance,
87 struct vk_object_base *object,
88 uint64_t base_address,
89 uint64_t size,
90 VkDeviceAddressBindingTypeEXT type)
91 {
92 if (list_is_empty(&instance->debug_utils.callbacks))
93 return;
94
95 VkDeviceAddressBindingCallbackDataEXT addr_binding = {
96 .sType = VK_STRUCTURE_TYPE_DEVICE_ADDRESS_BINDING_CALLBACK_DATA_EXT,
97 .flags = object->client_visible ? 0 : VK_DEVICE_ADDRESS_BINDING_INTERNAL_OBJECT_BIT_EXT,
98 .baseAddress = base_address,
99 .size = size,
100 .bindingType = type,
101 };
102
103 VkDebugUtilsObjectNameInfoEXT object_name_info = {
104 .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT,
105 .pNext = NULL,
106 .objectType = object->type,
107 .objectHandle = (uint64_t)(uintptr_t)object,
108 .pObjectName = object->object_name,
109 };
110
111 VkDebugUtilsMessengerCallbackDataEXT cb_data = {
112 .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT,
113 .pNext = &addr_binding,
114 .objectCount = 1,
115 .pObjects = &object_name_info,
116 };
117
118 vk_debug_message(instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT,
119 VK_DEBUG_UTILS_MESSAGE_TYPE_DEVICE_ADDRESS_BINDING_BIT_EXT,
120 &cb_data);
121 }
122
123 VKAPI_ATTR VkResult VKAPI_CALL
vk_common_CreateDebugUtilsMessengerEXT(VkInstance _instance,const VkDebugUtilsMessengerCreateInfoEXT * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDebugUtilsMessengerEXT * pMessenger)124 vk_common_CreateDebugUtilsMessengerEXT(
125 VkInstance _instance,
126 const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
127 const VkAllocationCallbacks *pAllocator,
128 VkDebugUtilsMessengerEXT *pMessenger)
129 {
130 VK_FROM_HANDLE(vk_instance, instance, _instance);
131
132 struct vk_debug_utils_messenger *messenger =
133 vk_alloc2(&instance->alloc, pAllocator,
134 sizeof(struct vk_debug_utils_messenger), 8,
135 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
136
137 if (!messenger)
138 return VK_ERROR_OUT_OF_HOST_MEMORY;
139
140 if (pAllocator)
141 messenger->alloc = *pAllocator;
142 else
143 messenger->alloc = instance->alloc;
144
145 vk_object_base_init(NULL, &messenger->base,
146 VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT);
147
148 messenger->severity = pCreateInfo->messageSeverity;
149 messenger->type = pCreateInfo->messageType;
150 messenger->callback = pCreateInfo->pfnUserCallback;
151 messenger->data = pCreateInfo->pUserData;
152
153 mtx_lock(&instance->debug_utils.callbacks_mutex);
154 list_addtail(&messenger->link, &instance->debug_utils.callbacks);
155 mtx_unlock(&instance->debug_utils.callbacks_mutex);
156
157 *pMessenger = vk_debug_utils_messenger_to_handle(messenger);
158
159 return VK_SUCCESS;
160 }
161
162 VKAPI_ATTR void VKAPI_CALL
vk_common_SubmitDebugUtilsMessageEXT(VkInstance _instance,VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,VkDebugUtilsMessageTypeFlagsEXT messageTypes,const VkDebugUtilsMessengerCallbackDataEXT * pCallbackData)163 vk_common_SubmitDebugUtilsMessageEXT(
164 VkInstance _instance,
165 VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
166 VkDebugUtilsMessageTypeFlagsEXT messageTypes,
167 const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData)
168 {
169 VK_FROM_HANDLE(vk_instance, instance, _instance);
170
171 vk_debug_message(instance, messageSeverity, messageTypes, pCallbackData);
172 }
173
174 VKAPI_ATTR void VKAPI_CALL
vk_common_DestroyDebugUtilsMessengerEXT(VkInstance _instance,VkDebugUtilsMessengerEXT _messenger,const VkAllocationCallbacks * pAllocator)175 vk_common_DestroyDebugUtilsMessengerEXT(
176 VkInstance _instance,
177 VkDebugUtilsMessengerEXT _messenger,
178 const VkAllocationCallbacks *pAllocator)
179 {
180 VK_FROM_HANDLE(vk_instance, instance, _instance);
181 VK_FROM_HANDLE(vk_debug_utils_messenger, messenger, _messenger);
182
183 if (messenger == NULL)
184 return;
185
186 mtx_lock(&instance->debug_utils.callbacks_mutex);
187 list_del(&messenger->link);
188 mtx_unlock(&instance->debug_utils.callbacks_mutex);
189
190 vk_object_base_finish(&messenger->base);
191 vk_free2(&instance->alloc, pAllocator, messenger);
192 }
193
194 static VkResult
vk_common_set_object_name_locked(struct vk_device * device,const VkDebugUtilsObjectNameInfoEXT * pNameInfo)195 vk_common_set_object_name_locked(
196 struct vk_device *device,
197 const VkDebugUtilsObjectNameInfoEXT *pNameInfo)
198 {
199 if (unlikely(device->swapchain_name == NULL)) {
200 /* Even though VkSwapchain/Surface are non-dispatchable objects, we know
201 * a priori that these are actually pointers so we can use
202 * the pointer hash table for them.
203 */
204 device->swapchain_name = _mesa_pointer_hash_table_create(NULL);
205 if (device->swapchain_name == NULL)
206 return VK_ERROR_OUT_OF_HOST_MEMORY;
207 }
208
209 char *object_name = vk_strdup(&device->alloc, pNameInfo->pObjectName,
210 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
211 if (object_name == NULL)
212 return VK_ERROR_OUT_OF_HOST_MEMORY;
213 struct hash_entry *entry =
214 _mesa_hash_table_search(device->swapchain_name,
215 (void *)(uintptr_t)pNameInfo->objectHandle);
216 if (unlikely(entry == NULL)) {
217 entry = _mesa_hash_table_insert(device->swapchain_name,
218 (void *)(uintptr_t)pNameInfo->objectHandle,
219 object_name);
220 if (entry == NULL) {
221 vk_free(&device->alloc, object_name);
222 return VK_ERROR_OUT_OF_HOST_MEMORY;
223 }
224 } else {
225 vk_free(&device->alloc, entry->data);
226 entry->data = object_name;
227 }
228 return VK_SUCCESS;
229 }
230
231 VKAPI_ATTR VkResult VKAPI_CALL
vk_common_DebugMarkerSetObjectNameEXT(VkDevice _device,const VkDebugMarkerObjectNameInfoEXT * pNameInfo)232 vk_common_DebugMarkerSetObjectNameEXT(
233 VkDevice _device,
234 const VkDebugMarkerObjectNameInfoEXT *pNameInfo)
235 {
236 VK_FROM_HANDLE(vk_device, device, _device);
237
238 assert(pNameInfo->sType == VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT);
239
240 VkObjectType object_type;
241 switch (pNameInfo->objectType) {
242 case VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT:
243 object_type = VK_OBJECT_TYPE_SURFACE_KHR;
244 break;
245 case VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT:
246 object_type = VK_OBJECT_TYPE_SWAPCHAIN_KHR;
247 break;
248 case VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT:
249 object_type = VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT;
250 break;
251 case VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT:
252 object_type = VK_OBJECT_TYPE_DISPLAY_KHR;
253 break;
254 case VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT:
255 object_type = VK_OBJECT_TYPE_DISPLAY_MODE_KHR;
256 break;
257 case VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT:
258 object_type = VK_OBJECT_TYPE_VALIDATION_CACHE_EXT;
259 break;
260 default:
261 object_type = (VkObjectType)pNameInfo->objectType;
262 break;
263 }
264
265 VkDebugUtilsObjectNameInfoEXT name_info = {
266 .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT,
267 .objectType = object_type,
268 .objectHandle = pNameInfo->object,
269 .pObjectName = pNameInfo->pObjectName,
270 };
271
272 return device->dispatch_table.SetDebugUtilsObjectNameEXT(_device, &name_info);
273 }
274
275 VKAPI_ATTR VkResult VKAPI_CALL
vk_common_SetDebugUtilsObjectNameEXT(VkDevice _device,const VkDebugUtilsObjectNameInfoEXT * pNameInfo)276 vk_common_SetDebugUtilsObjectNameEXT(
277 VkDevice _device,
278 const VkDebugUtilsObjectNameInfoEXT *pNameInfo)
279 {
280 VK_FROM_HANDLE(vk_device, device, _device);
281
282 #if DETECT_OS_ANDROID
283 if (pNameInfo->objectType == VK_OBJECT_TYPE_SWAPCHAIN_KHR ||
284 pNameInfo->objectType == VK_OBJECT_TYPE_SURFACE_KHR) {
285 #else
286 if (pNameInfo->objectType == VK_OBJECT_TYPE_SURFACE_KHR) {
287 #endif
288 mtx_lock(&device->swapchain_name_mtx);
289 VkResult res = vk_common_set_object_name_locked(device, pNameInfo);
290 mtx_unlock(&device->swapchain_name_mtx);
291 return res;
292 }
293
294 struct vk_object_base *object =
295 vk_object_base_from_u64_handle(pNameInfo->objectHandle,
296 pNameInfo->objectType);
297
298 assert(object->device != NULL || object->instance != NULL);
299 VkAllocationCallbacks *alloc = object->device != NULL ?
300 &object->device->alloc : &object->instance->alloc;
301 if (object->object_name) {
302 vk_free(alloc, object->object_name);
303 object->object_name = NULL;
304 }
305 if (pNameInfo->pObjectName != NULL) {
306 object->object_name = vk_strdup(alloc, pNameInfo->pObjectName,
307 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
308 if (!object->object_name)
309 return VK_ERROR_OUT_OF_HOST_MEMORY;
310 }
311
312 return VK_SUCCESS;
313 }
314
315 VKAPI_ATTR VkResult VKAPI_CALL
316 vk_common_SetDebugUtilsObjectTagEXT(
317 VkDevice _device,
318 const VkDebugUtilsObjectTagInfoEXT *pTagInfo)
319 {
320 /* no-op */
321 return VK_SUCCESS;
322 }
323
324 static void
325 vk_common_append_debug_label(struct vk_device *device,
326 struct util_dynarray *labels,
327 const VkDebugUtilsLabelEXT *pLabelInfo)
328 {
329 util_dynarray_append(labels, VkDebugUtilsLabelEXT, *pLabelInfo);
330 VkDebugUtilsLabelEXT *current_label =
331 util_dynarray_top_ptr(labels, VkDebugUtilsLabelEXT);
332 current_label->pLabelName =
333 vk_strdup(&device->alloc, current_label->pLabelName,
334 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
335 }
336
337 static void
338 vk_common_pop_debug_label(struct vk_device *device,
339 struct util_dynarray *labels)
340 {
341 if (labels->size == 0)
342 return;
343
344 VkDebugUtilsLabelEXT previous_label =
345 util_dynarray_pop(labels, VkDebugUtilsLabelEXT);
346 vk_free(&device->alloc, (void *)previous_label.pLabelName);
347 }
348
349 VKAPI_ATTR void VKAPI_CALL
350 vk_common_CmdBeginDebugUtilsLabelEXT(
351 VkCommandBuffer _commandBuffer,
352 const VkDebugUtilsLabelEXT *pLabelInfo)
353 {
354 VK_FROM_HANDLE(vk_command_buffer, command_buffer, _commandBuffer);
355
356 /* If the latest label was submitted by CmdInsertDebugUtilsLabelEXT, we
357 * should remove it first.
358 */
359 if (!command_buffer->region_begin) {
360 vk_common_pop_debug_label(command_buffer->base.device,
361 &command_buffer->labels);
362 }
363
364 vk_common_append_debug_label(command_buffer->base.device,
365 &command_buffer->labels,
366 pLabelInfo);
367 command_buffer->region_begin = true;
368 }
369
370 VKAPI_ATTR void VKAPI_CALL
371 vk_common_CmdEndDebugUtilsLabelEXT(VkCommandBuffer _commandBuffer)
372 {
373 VK_FROM_HANDLE(vk_command_buffer, command_buffer, _commandBuffer);
374
375 /* If the latest label was submitted by CmdInsertDebugUtilsLabelEXT, we
376 * should remove it first.
377 */
378 if (!command_buffer->region_begin) {
379 vk_common_pop_debug_label(command_buffer->base.device,
380 &command_buffer->labels);
381 }
382
383 vk_common_pop_debug_label(command_buffer->base.device,
384 &command_buffer->labels);
385 command_buffer->region_begin = true;
386 }
387
388 VKAPI_ATTR void VKAPI_CALL
389 vk_common_CmdInsertDebugUtilsLabelEXT(
390 VkCommandBuffer _commandBuffer,
391 const VkDebugUtilsLabelEXT *pLabelInfo)
392 {
393 VK_FROM_HANDLE(vk_command_buffer, command_buffer, _commandBuffer);
394
395 /* If the latest label was submitted by CmdInsertDebugUtilsLabelEXT, we
396 * should remove it first.
397 */
398 if (!command_buffer->region_begin) {
399 vk_common_append_debug_label(command_buffer->base.device,
400 &command_buffer->labels,
401 pLabelInfo);
402 }
403
404 vk_common_append_debug_label(command_buffer->base.device,
405 &command_buffer->labels,
406 pLabelInfo);
407 command_buffer->region_begin = false;
408 }
409
410 VKAPI_ATTR void VKAPI_CALL
411 vk_common_QueueBeginDebugUtilsLabelEXT(
412 VkQueue _queue,
413 const VkDebugUtilsLabelEXT *pLabelInfo)
414 {
415 VK_FROM_HANDLE(vk_queue, queue, _queue);
416
417 /* If the latest label was submitted by QueueInsertDebugUtilsLabelEXT, we
418 * should remove it first.
419 */
420 if (!queue->region_begin)
421 (void)util_dynarray_pop(&queue->labels, VkDebugUtilsLabelEXT);
422
423 vk_common_append_debug_label(queue->base.device,
424 &queue->labels,
425 pLabelInfo);
426 queue->region_begin = true;
427 }
428
429 VKAPI_ATTR void VKAPI_CALL
430 vk_common_QueueEndDebugUtilsLabelEXT(VkQueue _queue)
431 {
432 VK_FROM_HANDLE(vk_queue, queue, _queue);
433
434 /* If the latest label was submitted by QueueInsertDebugUtilsLabelEXT, we
435 * should remove it first.
436 */
437 if (!queue->region_begin)
438 vk_common_pop_debug_label(queue->base.device, &queue->labels);
439
440 vk_common_pop_debug_label(queue->base.device, &queue->labels);
441 queue->region_begin = true;
442 }
443
444 VKAPI_ATTR void VKAPI_CALL
445 vk_common_QueueInsertDebugUtilsLabelEXT(
446 VkQueue _queue,
447 const VkDebugUtilsLabelEXT *pLabelInfo)
448 {
449 VK_FROM_HANDLE(vk_queue, queue, _queue);
450
451 /* If the latest label was submitted by QueueInsertDebugUtilsLabelEXT, we
452 * should remove it first.
453 */
454 if (!queue->region_begin)
455 vk_common_pop_debug_label(queue->base.device, &queue->labels);
456
457 vk_common_append_debug_label(queue->base.device,
458 &queue->labels,
459 pLabelInfo);
460 queue->region_begin = false;
461 }
462