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