• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 static VkResult
vk_common_set_object_name_locked(struct vk_device * device,const VkDebugUtilsObjectNameInfoEXT * pNameInfo)157 vk_common_set_object_name_locked(
158    struct vk_device *device,
159    const VkDebugUtilsObjectNameInfoEXT *pNameInfo)
160 {
161    if (unlikely(device->swapchain_name == NULL)) {
162       /* Even though VkSwapchain/Surface are non-dispatchable objects, we know
163        * a priori that these are actually pointers so we can use
164        * the pointer hash table for them.
165        */
166       device->swapchain_name = _mesa_pointer_hash_table_create(NULL);
167       if (device->swapchain_name == NULL)
168          return VK_ERROR_OUT_OF_HOST_MEMORY;
169    }
170 
171    char *object_name = vk_strdup(&device->alloc, pNameInfo->pObjectName,
172                                  VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
173    if (object_name == NULL)
174       return VK_ERROR_OUT_OF_HOST_MEMORY;
175    struct hash_entry *entry =
176       _mesa_hash_table_search(device->swapchain_name,
177                               (void *)(uintptr_t)pNameInfo->objectHandle);
178    if (unlikely(entry == NULL)) {
179       entry = _mesa_hash_table_insert(device->swapchain_name,
180                                       (void *)(uintptr_t)pNameInfo->objectHandle,
181                                       object_name);
182       if (entry == NULL) {
183          vk_free(&device->alloc, object_name);
184          return VK_ERROR_OUT_OF_HOST_MEMORY;
185       }
186    } else {
187       vk_free(&device->alloc, entry->data);
188       entry->data = object_name;
189    }
190    return VK_SUCCESS;
191 }
192 
193 VKAPI_ATTR VkResult VKAPI_CALL
vk_common_SetDebugUtilsObjectNameEXT(VkDevice _device,const VkDebugUtilsObjectNameInfoEXT * pNameInfo)194 vk_common_SetDebugUtilsObjectNameEXT(
195    VkDevice _device,
196    const VkDebugUtilsObjectNameInfoEXT *pNameInfo)
197 {
198    VK_FROM_HANDLE(vk_device, device, _device);
199 
200 #if DETECT_OS_ANDROID
201    if (pNameInfo->objectType == VK_OBJECT_TYPE_SWAPCHAIN_KHR ||
202        pNameInfo->objectType == VK_OBJECT_TYPE_SURFACE_KHR) {
203 #else
204    if (pNameInfo->objectType == VK_OBJECT_TYPE_SURFACE_KHR) {
205 #endif
206       mtx_lock(&device->swapchain_name_mtx);
207       VkResult res = vk_common_set_object_name_locked(device, pNameInfo);
208       mtx_unlock(&device->swapchain_name_mtx);
209       return res;
210    }
211 
212    struct vk_object_base *object =
213       vk_object_base_from_u64_handle(pNameInfo->objectHandle,
214                                      pNameInfo->objectType);
215 
216    assert(object->device != NULL || object->instance != NULL);
217    VkAllocationCallbacks *alloc = object->device != NULL ?
218       &object->device->alloc : &object->instance->alloc;
219    if (object->object_name) {
220       vk_free(alloc, object->object_name);
221       object->object_name = NULL;
222    }
223    object->object_name = vk_strdup(alloc, pNameInfo->pObjectName,
224                                    VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
225    if (!object->object_name)
226       return VK_ERROR_OUT_OF_HOST_MEMORY;
227 
228    return VK_SUCCESS;
229 }
230 
231 VKAPI_ATTR VkResult VKAPI_CALL
232 vk_common_SetDebugUtilsObjectTagEXT(
233    VkDevice _device,
234    const VkDebugUtilsObjectTagInfoEXT *pTagInfo)
235 {
236    /* no-op */
237    return VK_SUCCESS;
238 }
239 
240 static void
241 vk_common_append_debug_label(struct vk_device *device,
242                              struct util_dynarray *labels,
243                              const VkDebugUtilsLabelEXT *pLabelInfo)
244 {
245    util_dynarray_append(labels, VkDebugUtilsLabelEXT, *pLabelInfo);
246    VkDebugUtilsLabelEXT *current_label =
247       util_dynarray_top_ptr(labels, VkDebugUtilsLabelEXT);
248    current_label->pLabelName =
249       vk_strdup(&device->alloc, current_label->pLabelName,
250                 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
251 }
252 
253 static void
254 vk_common_pop_debug_label(struct vk_device *device,
255                           struct util_dynarray *labels)
256 {
257    if (labels->size == 0)
258       return;
259 
260    VkDebugUtilsLabelEXT previous_label =
261       util_dynarray_pop(labels, VkDebugUtilsLabelEXT);
262    vk_free(&device->alloc, (void *)previous_label.pLabelName);
263 }
264 
265 VKAPI_ATTR void VKAPI_CALL
266 vk_common_CmdBeginDebugUtilsLabelEXT(
267    VkCommandBuffer _commandBuffer,
268    const VkDebugUtilsLabelEXT *pLabelInfo)
269 {
270    VK_FROM_HANDLE(vk_command_buffer, command_buffer, _commandBuffer);
271 
272    /* If the latest label was submitted by CmdInsertDebugUtilsLabelEXT, we
273     * should remove it first.
274     */
275    if (!command_buffer->region_begin) {
276       vk_common_pop_debug_label(command_buffer->base.device,
277                                 &command_buffer->labels);
278    }
279 
280    vk_common_append_debug_label(command_buffer->base.device,
281                                 &command_buffer->labels,
282                                 pLabelInfo);
283    command_buffer->region_begin = true;
284 }
285 
286 VKAPI_ATTR void VKAPI_CALL
287 vk_common_CmdEndDebugUtilsLabelEXT(VkCommandBuffer _commandBuffer)
288 {
289    VK_FROM_HANDLE(vk_command_buffer, command_buffer, _commandBuffer);
290 
291    /* If the latest label was submitted by CmdInsertDebugUtilsLabelEXT, we
292     * should remove it first.
293     */
294    if (!command_buffer->region_begin) {
295       vk_common_pop_debug_label(command_buffer->base.device,
296                                 &command_buffer->labels);
297    }
298 
299    vk_common_pop_debug_label(command_buffer->base.device,
300                              &command_buffer->labels);
301    command_buffer->region_begin = true;
302 }
303 
304 VKAPI_ATTR void VKAPI_CALL
305 vk_common_CmdInsertDebugUtilsLabelEXT(
306    VkCommandBuffer _commandBuffer,
307    const VkDebugUtilsLabelEXT *pLabelInfo)
308 {
309    VK_FROM_HANDLE(vk_command_buffer, command_buffer, _commandBuffer);
310 
311    /* If the latest label was submitted by CmdInsertDebugUtilsLabelEXT, we
312     * should remove it first.
313     */
314    if (!command_buffer->region_begin) {
315       vk_common_append_debug_label(command_buffer->base.device,
316                                    &command_buffer->labels,
317                                    pLabelInfo);
318    }
319 
320    vk_common_append_debug_label(command_buffer->base.device,
321                                 &command_buffer->labels,
322                                 pLabelInfo);
323    command_buffer->region_begin = false;
324 }
325 
326 VKAPI_ATTR void VKAPI_CALL
327 vk_common_QueueBeginDebugUtilsLabelEXT(
328    VkQueue _queue,
329    const VkDebugUtilsLabelEXT *pLabelInfo)
330 {
331    VK_FROM_HANDLE(vk_queue, queue, _queue);
332 
333    /* If the latest label was submitted by QueueInsertDebugUtilsLabelEXT, we
334     * should remove it first.
335     */
336    if (!queue->region_begin)
337       (void)util_dynarray_pop(&queue->labels, VkDebugUtilsLabelEXT);
338 
339    vk_common_append_debug_label(queue->base.device,
340                                 &queue->labels,
341                                 pLabelInfo);
342    queue->region_begin = true;
343 }
344 
345 VKAPI_ATTR void VKAPI_CALL
346 vk_common_QueueEndDebugUtilsLabelEXT(VkQueue _queue)
347 {
348    VK_FROM_HANDLE(vk_queue, queue, _queue);
349 
350    /* If the latest label was submitted by QueueInsertDebugUtilsLabelEXT, we
351     * should remove it first.
352     */
353    if (!queue->region_begin)
354       vk_common_pop_debug_label(queue->base.device, &queue->labels);
355 
356    vk_common_pop_debug_label(queue->base.device, &queue->labels);
357    queue->region_begin = true;
358 }
359 
360 VKAPI_ATTR void VKAPI_CALL
361 vk_common_QueueInsertDebugUtilsLabelEXT(
362    VkQueue _queue,
363    const VkDebugUtilsLabelEXT *pLabelInfo)
364 {
365    VK_FROM_HANDLE(vk_queue, queue, _queue);
366 
367    /* If the latest label was submitted by QueueInsertDebugUtilsLabelEXT, we
368     * should remove it first.
369     */
370    if (!queue->region_begin)
371       vk_common_pop_debug_label(queue->base.device, &queue->labels);
372 
373    vk_common_append_debug_label(queue->base.device,
374                                 &queue->labels,
375                                 pLabelInfo);
376    queue->region_begin = false;
377 }
378