17ec681f3Smrg/* 27ec681f3Smrg * Copyright © 2021 Intel Corporation 37ec681f3Smrg * 47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 57ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 67ec681f3Smrg * to deal in the Software without restriction, including without limitation 77ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 87ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the 97ec681f3Smrg * Software is furnished to do so, subject to the following conditions: 107ec681f3Smrg * 117ec681f3Smrg * The above copyright notice and this permission notice (including the next 127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the 137ec681f3Smrg * Software. 147ec681f3Smrg * 157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 187ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 197ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 207ec681f3Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 217ec681f3Smrg * IN THE SOFTWARE. 227ec681f3Smrg */ 237ec681f3Smrg 247ec681f3Smrg#include "vk_log.h" 257ec681f3Smrg#include "vk_debug_utils.h" 267ec681f3Smrg#include "vk_debug_report.h" 277ec681f3Smrg 287ec681f3Smrg#include "vk_command_buffer.h" 297ec681f3Smrg#include "vk_enum_to_str.h" 307ec681f3Smrg#include "vk_queue.h" 317ec681f3Smrg#include "vk_device.h" 327ec681f3Smrg#include "vk_physical_device.h" 337ec681f3Smrg 347ec681f3Smrg#include "ralloc.h" 357ec681f3Smrg 367ec681f3Smrg#include "log.h" 377ec681f3Smrg 387ec681f3Smrgstatic struct vk_device * 397ec681f3Smrgvk_object_to_device(struct vk_object_base *obj) 407ec681f3Smrg{ 417ec681f3Smrg assert(obj->device); 427ec681f3Smrg return obj->device; 437ec681f3Smrg} 447ec681f3Smrg 457ec681f3Smrgstatic struct vk_physical_device * 467ec681f3Smrgvk_object_to_physical_device(struct vk_object_base *obj) 477ec681f3Smrg{ 487ec681f3Smrg switch (obj->type) { 497ec681f3Smrg case VK_OBJECT_TYPE_INSTANCE: 507ec681f3Smrg unreachable("Unsupported object type"); 517ec681f3Smrg case VK_OBJECT_TYPE_PHYSICAL_DEVICE: 527ec681f3Smrg return container_of(obj, struct vk_physical_device, base); 537ec681f3Smrg case VK_OBJECT_TYPE_SURFACE_KHR: 547ec681f3Smrg case VK_OBJECT_TYPE_DISPLAY_KHR: 557ec681f3Smrg case VK_OBJECT_TYPE_DISPLAY_MODE_KHR: 567ec681f3Smrg case VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT: 577ec681f3Smrg case VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT: 587ec681f3Smrg unreachable("Unsupported object type"); 597ec681f3Smrg default: 607ec681f3Smrg return vk_object_to_device(obj)->physical; 617ec681f3Smrg } 627ec681f3Smrg} 637ec681f3Smrg 647ec681f3Smrgstatic struct vk_instance * 657ec681f3Smrgvk_object_to_instance(struct vk_object_base *obj) 667ec681f3Smrg{ 677ec681f3Smrg if (obj == NULL) 687ec681f3Smrg return NULL; 697ec681f3Smrg 707ec681f3Smrg if (obj->type == VK_OBJECT_TYPE_INSTANCE) { 717ec681f3Smrg return container_of(obj, struct vk_instance, base); 727ec681f3Smrg } else { 737ec681f3Smrg return vk_object_to_physical_device(obj)->instance; 747ec681f3Smrg } 757ec681f3Smrg} 767ec681f3Smrg 777ec681f3Smrgvoid 787ec681f3Smrg__vk_log_impl(VkDebugUtilsMessageSeverityFlagBitsEXT severity, 797ec681f3Smrg VkDebugUtilsMessageTypeFlagsEXT types, 807ec681f3Smrg int object_count, 817ec681f3Smrg const void **objects_or_instance, 827ec681f3Smrg const char *file, 837ec681f3Smrg int line, 847ec681f3Smrg const char *format, 857ec681f3Smrg ...) 867ec681f3Smrg{ 877ec681f3Smrg struct vk_instance *instance = NULL; 887ec681f3Smrg struct vk_object_base **objects = NULL; 897ec681f3Smrg if (object_count == 0) { 907ec681f3Smrg instance = (struct vk_instance *) objects_or_instance; 917ec681f3Smrg } else { 927ec681f3Smrg objects = (struct vk_object_base **) objects_or_instance; 937ec681f3Smrg instance = vk_object_to_instance(objects[0]); 947ec681f3Smrg assert(instance->base.client_visible); 957ec681f3Smrg } 967ec681f3Smrg 977ec681f3Smrg#ifndef DEBUG 987ec681f3Smrg if (unlikely(!instance) || 997ec681f3Smrg (likely(list_is_empty(&instance->debug_utils.callbacks)) && 1007ec681f3Smrg likely(list_is_empty(&instance->debug_report.callbacks)))) 1017ec681f3Smrg return; 1027ec681f3Smrg#endif 1037ec681f3Smrg 1047ec681f3Smrg va_list va; 1057ec681f3Smrg char *message = NULL; 1067ec681f3Smrg 1077ec681f3Smrg va_start(va, format); 1087ec681f3Smrg message = ralloc_vasprintf(NULL, format, va); 1097ec681f3Smrg va_end(va); 1107ec681f3Smrg 1117ec681f3Smrg char *message_idname = ralloc_asprintf(NULL, "%s:%d", file, line); 1127ec681f3Smrg 1137ec681f3Smrg#if DEBUG 1147ec681f3Smrg switch (severity) { 1157ec681f3Smrg case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: 1167ec681f3Smrg mesa_logd("%s: %s", message_idname, message); 1177ec681f3Smrg break; 1187ec681f3Smrg case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: 1197ec681f3Smrg mesa_logi("%s: %s", message_idname, message); 1207ec681f3Smrg break; 1217ec681f3Smrg case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: 1227ec681f3Smrg if (types & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) 1237ec681f3Smrg mesa_logw("%s: PERF: %s", message_idname, message); 1247ec681f3Smrg else 1257ec681f3Smrg mesa_logw("%s: %s", message_idname, message); 1267ec681f3Smrg break; 1277ec681f3Smrg case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: 1287ec681f3Smrg mesa_loge("%s: %s", message_idname, message); 1297ec681f3Smrg break; 1307ec681f3Smrg default: 1317ec681f3Smrg unreachable("Invalid debug message severity"); 1327ec681f3Smrg break; 1337ec681f3Smrg } 1347ec681f3Smrg 1357ec681f3Smrg if (!instance) { 1367ec681f3Smrg ralloc_free(message); 1377ec681f3Smrg ralloc_free(message_idname); 1387ec681f3Smrg return; 1397ec681f3Smrg } 1407ec681f3Smrg#endif 1417ec681f3Smrg 1427ec681f3Smrg if (!instance->base.client_visible) { 1437ec681f3Smrg vk_debug_message_instance(instance, severity, types, 1447ec681f3Smrg message_idname, 0, message); 1457ec681f3Smrg ralloc_free(message); 1467ec681f3Smrg ralloc_free(message_idname); 1477ec681f3Smrg return; 1487ec681f3Smrg } 1497ec681f3Smrg 1507ec681f3Smrg /* If VK_EXT_debug_utils messengers have been set up, form the 1517ec681f3Smrg * message */ 1527ec681f3Smrg if (!list_is_empty(&instance->debug_utils.callbacks)) { 1537ec681f3Smrg VkDebugUtilsMessengerCallbackDataEXT cb_data = { 1547ec681f3Smrg .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT, 1557ec681f3Smrg .pMessageIdName = message_idname, 1567ec681f3Smrg .messageIdNumber = 0, 1577ec681f3Smrg .pMessage = message, 1587ec681f3Smrg }; 1597ec681f3Smrg 1607ec681f3Smrg VkDebugUtilsObjectNameInfoEXT *object_name_infos = 1617ec681f3Smrg ralloc_array(NULL, VkDebugUtilsObjectNameInfoEXT, object_count); 1627ec681f3Smrg 1637ec681f3Smrg ASSERTED int cmdbuf_n = 0, queue_n = 0; 1647ec681f3Smrg for (int i = 0; i < object_count; i++) { 1657ec681f3Smrg struct vk_object_base *base = objects[i]; 1667ec681f3Smrg assert(base->client_visible); 1677ec681f3Smrg 1687ec681f3Smrg switch (base->type) { 1697ec681f3Smrg case VK_OBJECT_TYPE_COMMAND_BUFFER: { 1707ec681f3Smrg /* We allow at most one command buffer to be submitted at a time */ 1717ec681f3Smrg assert(++cmdbuf_n <= 1); 1727ec681f3Smrg struct vk_command_buffer *cmd_buffer = 1737ec681f3Smrg (struct vk_command_buffer *)base; 1747ec681f3Smrg if (cmd_buffer->labels.size > 0) { 1757ec681f3Smrg cb_data.cmdBufLabelCount = util_dynarray_num_elements( 1767ec681f3Smrg &cmd_buffer->labels, VkDebugUtilsLabelEXT); 1777ec681f3Smrg cb_data.pCmdBufLabels = cmd_buffer->labels.data; 1787ec681f3Smrg } 1797ec681f3Smrg break; 1807ec681f3Smrg } 1817ec681f3Smrg 1827ec681f3Smrg case VK_OBJECT_TYPE_QUEUE: { 1837ec681f3Smrg /* We allow at most one queue to be submitted at a time */ 1847ec681f3Smrg assert(++queue_n <= 1); 1857ec681f3Smrg struct vk_queue *queue = (struct vk_queue *)base; 1867ec681f3Smrg if (queue->labels.size > 0) { 1877ec681f3Smrg cb_data.queueLabelCount = 1887ec681f3Smrg util_dynarray_num_elements(&queue->labels, VkDebugUtilsLabelEXT); 1897ec681f3Smrg cb_data.pQueueLabels = queue->labels.data; 1907ec681f3Smrg } 1917ec681f3Smrg break; 1927ec681f3Smrg } 1937ec681f3Smrg default: 1947ec681f3Smrg break; 1957ec681f3Smrg } 1967ec681f3Smrg 1977ec681f3Smrg object_name_infos[i] = (VkDebugUtilsObjectNameInfoEXT){ 1987ec681f3Smrg .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, 1997ec681f3Smrg .pNext = NULL, 2007ec681f3Smrg .objectType = base->type, 2017ec681f3Smrg .objectHandle = (uint64_t)(uintptr_t)base, 2027ec681f3Smrg .pObjectName = base->object_name, 2037ec681f3Smrg }; 2047ec681f3Smrg } 2057ec681f3Smrg cb_data.objectCount = object_count; 2067ec681f3Smrg cb_data.pObjects = object_name_infos; 2077ec681f3Smrg 2087ec681f3Smrg vk_debug_message(instance, severity, types, &cb_data); 2097ec681f3Smrg 2107ec681f3Smrg ralloc_free(object_name_infos); 2117ec681f3Smrg } 2127ec681f3Smrg 2137ec681f3Smrg /* If VK_EXT_debug_report callbacks also have been set up, forward 2147ec681f3Smrg * the message there as well */ 2157ec681f3Smrg if (!list_is_empty(&instance->debug_report.callbacks)) { 2167ec681f3Smrg VkDebugReportFlagsEXT flags = 0; 2177ec681f3Smrg 2187ec681f3Smrg switch (severity) { 2197ec681f3Smrg case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: 2207ec681f3Smrg flags |= VK_DEBUG_REPORT_DEBUG_BIT_EXT; 2217ec681f3Smrg break; 2227ec681f3Smrg case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: 2237ec681f3Smrg flags |= VK_DEBUG_REPORT_INFORMATION_BIT_EXT; 2247ec681f3Smrg break; 2257ec681f3Smrg case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: 2267ec681f3Smrg if (types & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) 2277ec681f3Smrg flags |= VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; 2287ec681f3Smrg else 2297ec681f3Smrg flags |= VK_DEBUG_REPORT_WARNING_BIT_EXT; 2307ec681f3Smrg break; 2317ec681f3Smrg case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: 2327ec681f3Smrg flags |= VK_DEBUG_REPORT_ERROR_BIT_EXT; 2337ec681f3Smrg break; 2347ec681f3Smrg default: 2357ec681f3Smrg unreachable("Invalid debug message severity"); 2367ec681f3Smrg break; 2377ec681f3Smrg } 2387ec681f3Smrg 2397ec681f3Smrg /* VK_EXT_debug_report-provided callback accepts only one object 2407ec681f3Smrg * related to the message. Since they are given to us in 2417ec681f3Smrg * decreasing order of importance, we're forwarding the first 2427ec681f3Smrg * one. 2437ec681f3Smrg */ 2447ec681f3Smrg vk_debug_report(instance, flags, object_count ? objects[0] : NULL, 0, 2457ec681f3Smrg 0, message_idname, message); 2467ec681f3Smrg } 2477ec681f3Smrg 2487ec681f3Smrg ralloc_free(message); 2497ec681f3Smrg ralloc_free(message_idname); 2507ec681f3Smrg} 2517ec681f3Smrg 2527ec681f3Smrgstatic struct vk_object_base * 2537ec681f3Smrgvk_object_for_error(struct vk_object_base *obj, VkResult error) 2547ec681f3Smrg{ 2557ec681f3Smrg if (obj == NULL) 2567ec681f3Smrg return NULL; 2577ec681f3Smrg 2587ec681f3Smrg switch (error) { 2597ec681f3Smrg case VK_ERROR_OUT_OF_HOST_MEMORY: 2607ec681f3Smrg case VK_ERROR_LAYER_NOT_PRESENT: 2617ec681f3Smrg case VK_ERROR_EXTENSION_NOT_PRESENT: 2627ec681f3Smrg case VK_ERROR_UNKNOWN: 2637ec681f3Smrg return &vk_object_to_instance(obj)->base; 2647ec681f3Smrg case VK_ERROR_FEATURE_NOT_PRESENT: 2657ec681f3Smrg return &vk_object_to_physical_device(obj)->base; 2667ec681f3Smrg case VK_ERROR_OUT_OF_DEVICE_MEMORY: 2677ec681f3Smrg case VK_ERROR_MEMORY_MAP_FAILED: 2687ec681f3Smrg case VK_ERROR_TOO_MANY_OBJECTS: 2697ec681f3Smrg return &vk_object_to_device(obj)->base; 2707ec681f3Smrg default: 2717ec681f3Smrg return obj; 2727ec681f3Smrg } 2737ec681f3Smrg} 2747ec681f3Smrg 2757ec681f3SmrgVkResult 2767ec681f3Smrg__vk_errorv(const void *_obj, VkResult error, 2777ec681f3Smrg const char *file, int line, 2787ec681f3Smrg const char *format, va_list va) 2797ec681f3Smrg{ 2807ec681f3Smrg struct vk_object_base *object = (struct vk_object_base *)_obj; 2817ec681f3Smrg struct vk_instance *instance = vk_object_to_instance(object); 2827ec681f3Smrg object = vk_object_for_error(object, error); 2837ec681f3Smrg 2847ec681f3Smrg /* If object->client_visible isn't set then the object hasn't been fully 2857ec681f3Smrg * constructed and we shouldn't hand it back to the client. This typically 2867ec681f3Smrg * happens if an error is thrown during object construction. This is safe 2877ec681f3Smrg * to do as long as vk_object_base_init() has already been called. 2887ec681f3Smrg */ 2897ec681f3Smrg if (object && !object->client_visible) 2907ec681f3Smrg object = NULL; 2917ec681f3Smrg 2927ec681f3Smrg const char *error_str = vk_Result_to_str(error); 2937ec681f3Smrg 2947ec681f3Smrg if (format) { 2957ec681f3Smrg char *message = ralloc_vasprintf(NULL, format, va); 2967ec681f3Smrg 2977ec681f3Smrg if (object) { 2987ec681f3Smrg __vk_log(VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, 2997ec681f3Smrg VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, 3007ec681f3Smrg VK_LOG_OBJS(object), file, line, 3017ec681f3Smrg "%s (%s)", message, error_str); 3027ec681f3Smrg } else { 3037ec681f3Smrg __vk_log(VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, 3047ec681f3Smrg VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, 3057ec681f3Smrg VK_LOG_NO_OBJS(instance), file, line, 3067ec681f3Smrg "%s (%s)", message, error_str); 3077ec681f3Smrg } 3087ec681f3Smrg 3097ec681f3Smrg ralloc_free(message); 3107ec681f3Smrg } else { 3117ec681f3Smrg if (object) { 3127ec681f3Smrg __vk_log(VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, 3137ec681f3Smrg VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, 3147ec681f3Smrg VK_LOG_OBJS(object), file, line, 3157ec681f3Smrg "%s", error_str); 3167ec681f3Smrg } else { 3177ec681f3Smrg __vk_log(VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, 3187ec681f3Smrg VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, 3197ec681f3Smrg VK_LOG_NO_OBJS(instance), file, line, 3207ec681f3Smrg "%s", error_str); 3217ec681f3Smrg } 3227ec681f3Smrg } 3237ec681f3Smrg 3247ec681f3Smrg return error; 3257ec681f3Smrg} 3267ec681f3Smrg 3277ec681f3SmrgVkResult 3287ec681f3Smrg__vk_errorf(const void *_obj, VkResult error, 3297ec681f3Smrg const char *file, int line, 3307ec681f3Smrg const char *format, ...) 3317ec681f3Smrg{ 3327ec681f3Smrg va_list va; 3337ec681f3Smrg 3347ec681f3Smrg va_start(va, format); 3357ec681f3Smrg VkResult result = __vk_errorv(_obj, error, file, line, format, va); 3367ec681f3Smrg va_end(va); 3377ec681f3Smrg 3387ec681f3Smrg return result; 3397ec681f3Smrg} 340