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