• 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 #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