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