From d55d1fcda2f5f1cd20dcc240fd75ade66f8177f7 Mon Sep 17 00:00:00 2001 From: Yevhenii Kolesnikov Date: Wed, 22 Sep 2021 01:56:38 +0300 Subject: [PATCH] vulkan: Add convenience debug message helpers Forwards the message to both VK_EXT_debug_utils and VK_EXT_debug_report provided callbacks. Signed-off-by: Yevhenii Kolesnikov Reviewed-by: Jason Ekstrand Part-of: --- src/vulkan/util/meson.build | 2 + src/vulkan/util/vk_log.c | 200 ++++++++++++++++++++++++++++++++++++ src/vulkan/util/vk_log.h | 73 +++++++++++++ src/vulkan/util/vk_object.c | 16 +++ src/vulkan/util/vk_object.h | 3 + 5 files changed, 294 insertions(+) create mode 100644 src/vulkan/util/vk_log.c create mode 100644 src/vulkan/util/vk_log.h diff --git a/src/vulkan/util/meson.build b/src/vulkan/util/meson.build index 1bfd7a6cddd..dddcfad3e0c 100644 --- a/src/vulkan/util/meson.build +++ b/src/vulkan/util/meson.build @@ -69,6 +69,8 @@ files_vulkan_util = files( 'vk_image.h', 'vk_instance.c', 'vk_instance.h', + 'vk_log.c', + 'vk_log.h', 'vk_object.c', 'vk_object.h', 'vk_physical_device.c', diff --git a/src/vulkan/util/vk_log.c b/src/vulkan/util/vk_log.c new file mode 100644 index 00000000000..66929ab40a3 --- /dev/null +++ b/src/vulkan/util/vk_log.c @@ -0,0 +1,200 @@ +/* + * Copyright © 2021 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "vk_log.h" +#include "vk_debug_utils.h" +#include "vk_debug_report.h" + +#include "vk_command_buffer.h" +#include "vk_queue.h" +#include "vk_device.h" +#include "vk_physical_device.h" + +#include "ralloc.h" + +#include "log.h" + +void +__vk_log_impl(VkDebugUtilsMessageSeverityFlagBitsEXT severity, + VkDebugUtilsMessageTypeFlagsEXT types, + int object_count, + const void **objects_or_instance, + const char *file, + int line, + const char *format, + ...) +{ + struct vk_instance *instance = NULL; + struct vk_object_base **objects = NULL; + if (object_count == 0) { + instance = (struct vk_instance *) objects_or_instance; + } else { + objects = (struct vk_object_base **) objects_or_instance; + instance = objects[0]->device->physical->instance; + } + +#ifndef DEBUG + if (unlikely(!instance) || + (likely(list_is_empty(&instance->debug_utils.callbacks)) && + likely(list_is_empty(&instance->debug_report.callbacks)))) + return; +#endif + + va_list va; + char *message = NULL; + + va_start(va, format); + message = ralloc_vasprintf(NULL, format, va); + va_end(va); + + char *message_idname = ralloc_asprintf(NULL, "%s:%d", file, line); + +#if DEBUG + switch (severity) { + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: + mesa_logd("%s: %s", message_idname, message); + break; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: + mesa_logi("%s: %s", message_idname, message); + break; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: + if (types & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) + mesa_logw("%s: PERF: %s", message_idname, message); + else + mesa_logw("%s: %s", message_idname, message); + break; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: + mesa_loge("%s: %s", message_idname, message); + break; + default: + unreachable("Invalid debug message severity"); + break; + } + + if (!instance) { + ralloc_free(message); + ralloc_free(message_idname); + return; + } +#endif + + /* If VK_EXT_debug_utils messengers have been set up, form the + * message */ + if (!list_is_empty(&instance->debug_utils.callbacks)) { + VkDebugUtilsMessengerCallbackDataEXT cb_data = { + .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT, + .pMessageIdName = message_idname, + .messageIdNumber = 0, + .pMessage = message, + }; + + VkDebugUtilsObjectNameInfoEXT *object_name_infos = + ralloc_array(NULL, VkDebugUtilsObjectNameInfoEXT, object_count); + + ASSERTED int cmdbuf_n = 0, queue_n = 0; + for (int i = 0; i < object_count; i++) { + struct vk_object_base *base = objects[i]; + + switch (base->type) { + case VK_OBJECT_TYPE_COMMAND_BUFFER: { + /* We allow at most one command buffer to be submitted at a time */ + assert(++cmdbuf_n <= 1); + struct vk_command_buffer *cmd_buffer = + (struct vk_command_buffer *)base; + if (cmd_buffer->labels.size > 0) { + cb_data.cmdBufLabelCount = util_dynarray_num_elements( + &cmd_buffer->labels, VkDebugUtilsLabelEXT); + cb_data.pCmdBufLabels = cmd_buffer->labels.data; + } + break; + } + + case VK_OBJECT_TYPE_QUEUE: { + /* We allow at most one queue to be submitted at a time */ + assert(++queue_n <= 1); + struct vk_queue *queue = (struct vk_queue *)base; + if (queue->labels.size > 0) { + cb_data.queueLabelCount = + util_dynarray_num_elements(&queue->labels, VkDebugUtilsLabelEXT); + cb_data.pQueueLabels = queue->labels.data; + } + break; + } + default: + break; + } + + object_name_infos[i] = (VkDebugUtilsObjectNameInfoEXT){ + .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, + .pNext = NULL, + .objectType = base->type, + .objectHandle = (uint64_t)(uintptr_t)base, + .pObjectName = base->object_name, + }; + } + cb_data.objectCount = object_count; + cb_data.pObjects = object_name_infos; + + vk_debug_message(instance, severity, types, &cb_data); + + ralloc_free(object_name_infos); + } + + /* If VK_EXT_debug_report callbacks also have been set up, forward + * the message there as well */ + if (!list_is_empty(&instance->debug_report.callbacks)) { + VkDebugReportFlagsEXT flags = 0; + + switch (severity) { + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: + flags |= VK_DEBUG_REPORT_DEBUG_BIT_EXT; + break; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: + flags |= VK_DEBUG_REPORT_INFORMATION_BIT_EXT; + break; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: + if (types & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) + flags |= VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; + else + flags |= VK_DEBUG_REPORT_WARNING_BIT_EXT; + break; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: + flags |= VK_DEBUG_REPORT_ERROR_BIT_EXT; + break; + default: + unreachable("Invalid debug message severity"); + break; + } + + /* VK_EXT_debug_report-provided callback accepts only one object + * related to the message. Since they are given to us in + * decreasing order of importance, we're forwarding the first + * one. + */ + vk_debug_report(instance, flags, object_count ? objects[0] : NULL, 0, + 0, message_idname, message); + } + + ralloc_free(message); + ralloc_free(message_idname); +} diff --git a/src/vulkan/util/vk_log.h b/src/vulkan/util/vk_log.h new file mode 100644 index 00000000000..0e33d8949c5 --- /dev/null +++ b/src/vulkan/util/vk_log.h @@ -0,0 +1,73 @@ +/* + * Copyright © 2021 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "vk_instance.h" + +/* __VK_ARG_N(...) returns the number of arguments provided to it */ +#define __VK_ARG_SEQ(_1,_2,_3,_4,_5,_6,_7,_8,N,...) N +#define __VK_ARG_N(...) __VK_ARG_SEQ(__VA_ARGS__,8,7,6,5,4,3,2,1,0) + +#define VK_LOG_OBJS(...) \ + __VK_ARG_N(__VA_ARGS__), (const void*[]){__VA_ARGS__} + +#define VK_LOG_NO_OBJS(instance) 0, (const void**)instance + +#define vk_logd(objects_macro, format, ...) \ + __vk_log(VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT, \ + VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, \ + objects_macro, __FILE__, __LINE__, format, ## __VA_ARGS__) + +#define vk_logi(objects_macro, format, ...) \ + __vk_log(VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT, \ + VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, \ + objects_macro, __FILE__, __LINE__, format, ## __VA_ARGS__) + +#define vk_logw(objects_macro, format, ...) \ + __vk_log(VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT, \ + VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, \ + objects_macro, __FILE__, __LINE__, format, ## __VA_ARGS__) + +#define vk_loge(objects_macro, format, ...) \ + __vk_log(VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, \ + VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, \ + objects_macro, __FILE__, __LINE__, format, ## __VA_ARGS__) + +#define vk_perf(objects_macro, format, ...) \ + __vk_log(VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT, \ + VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT, \ + objects_macro, __FILE__, __LINE__, format, ## __VA_ARGS__) + +#define __vk_log(severity, type, object_count, \ + objects_or_instance, file, line, format, ...) \ + __vk_log_impl(severity, type, object_count, objects_or_instance, \ + file, line, format, ## __VA_ARGS__) + +void PRINTFLIKE(7, 8) +__vk_log_impl(VkDebugUtilsMessageSeverityFlagBitsEXT severity, + VkDebugUtilsMessageTypeFlagsEXT types, + int object_count, + const void **objects_or_instance, + const char *file, + int line, + const char *format, + ...); diff --git a/src/vulkan/util/vk_object.c b/src/vulkan/util/vk_object.c index 08f1eeea5ad..b3e482ef133 100644 --- a/src/vulkan/util/vk_object.c +++ b/src/vulkan/util/vk_object.c @@ -28,6 +28,7 @@ #include "vk_device.h" #include "util/hash_table.h" #include "util/ralloc.h" +#include "vk_enum_to_str.h" static void vk_object_base_reinit(struct vk_object_base *base) @@ -326,3 +327,18 @@ vk_common_GetPrivateDataEXT(VkDevice _device, objectType, objectHandle, privateDataSlot, pData); } + +const char * +vk_object_base_name(struct vk_object_base *obj) +{ + if (obj->object_name) + return obj->object_name; + + obj->object_name = vk_asprintf(&obj->device->alloc, + VK_SYSTEM_ALLOCATION_SCOPE_DEVICE, + "%s(0x%"PRIx64")", + vk_ObjectType_to_ObjectName(obj->type), + (uint64_t)(uintptr_t)obj); + + return obj->object_name; +} diff --git a/src/vulkan/util/vk_object.h b/src/vulkan/util/vk_object.h index ebaa2376997..d23713580aa 100644 --- a/src/vulkan/util/vk_object.h +++ b/src/vulkan/util/vk_object.h @@ -173,6 +173,9 @@ vk_object_base_get_private_data(struct vk_device *device, VkPrivateDataSlotEXT privateDataSlot, uint64_t *pData); +const char * +vk_object_base_name(struct vk_object_base *obj); + #ifdef __cplusplus } #endif