xref: /aosp_15_r20/external/mesa3d/src/vulkan/runtime/vk_debug_utils.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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