vk_log.c revision 7ec681f3
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_log.h" 25#include "vk_debug_utils.h" 26#include "vk_debug_report.h" 27 28#include "vk_command_buffer.h" 29#include "vk_enum_to_str.h" 30#include "vk_queue.h" 31#include "vk_device.h" 32#include "vk_physical_device.h" 33 34#include "ralloc.h" 35 36#include "log.h" 37 38static struct vk_device * 39vk_object_to_device(struct vk_object_base *obj) 40{ 41 assert(obj->device); 42 return obj->device; 43} 44 45static struct vk_physical_device * 46vk_object_to_physical_device(struct vk_object_base *obj) 47{ 48 switch (obj->type) { 49 case VK_OBJECT_TYPE_INSTANCE: 50 unreachable("Unsupported object type"); 51 case VK_OBJECT_TYPE_PHYSICAL_DEVICE: 52 return container_of(obj, struct vk_physical_device, base); 53 case VK_OBJECT_TYPE_SURFACE_KHR: 54 case VK_OBJECT_TYPE_DISPLAY_KHR: 55 case VK_OBJECT_TYPE_DISPLAY_MODE_KHR: 56 case VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT: 57 case VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT: 58 unreachable("Unsupported object type"); 59 default: 60 return vk_object_to_device(obj)->physical; 61 } 62} 63 64static struct vk_instance * 65vk_object_to_instance(struct vk_object_base *obj) 66{ 67 if (obj == NULL) 68 return NULL; 69 70 if (obj->type == VK_OBJECT_TYPE_INSTANCE) { 71 return container_of(obj, struct vk_instance, base); 72 } else { 73 return vk_object_to_physical_device(obj)->instance; 74 } 75} 76 77void 78__vk_log_impl(VkDebugUtilsMessageSeverityFlagBitsEXT severity, 79 VkDebugUtilsMessageTypeFlagsEXT types, 80 int object_count, 81 const void **objects_or_instance, 82 const char *file, 83 int line, 84 const char *format, 85 ...) 86{ 87 struct vk_instance *instance = NULL; 88 struct vk_object_base **objects = NULL; 89 if (object_count == 0) { 90 instance = (struct vk_instance *) objects_or_instance; 91 } else { 92 objects = (struct vk_object_base **) objects_or_instance; 93 instance = vk_object_to_instance(objects[0]); 94 assert(instance->base.client_visible); 95 } 96 97#ifndef DEBUG 98 if (unlikely(!instance) || 99 (likely(list_is_empty(&instance->debug_utils.callbacks)) && 100 likely(list_is_empty(&instance->debug_report.callbacks)))) 101 return; 102#endif 103 104 va_list va; 105 char *message = NULL; 106 107 va_start(va, format); 108 message = ralloc_vasprintf(NULL, format, va); 109 va_end(va); 110 111 char *message_idname = ralloc_asprintf(NULL, "%s:%d", file, line); 112 113#if DEBUG 114 switch (severity) { 115 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: 116 mesa_logd("%s: %s", message_idname, message); 117 break; 118 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: 119 mesa_logi("%s: %s", message_idname, message); 120 break; 121 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: 122 if (types & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) 123 mesa_logw("%s: PERF: %s", message_idname, message); 124 else 125 mesa_logw("%s: %s", message_idname, message); 126 break; 127 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: 128 mesa_loge("%s: %s", message_idname, message); 129 break; 130 default: 131 unreachable("Invalid debug message severity"); 132 break; 133 } 134 135 if (!instance) { 136 ralloc_free(message); 137 ralloc_free(message_idname); 138 return; 139 } 140#endif 141 142 if (!instance->base.client_visible) { 143 vk_debug_message_instance(instance, severity, types, 144 message_idname, 0, message); 145 ralloc_free(message); 146 ralloc_free(message_idname); 147 return; 148 } 149 150 /* If VK_EXT_debug_utils messengers have been set up, form the 151 * message */ 152 if (!list_is_empty(&instance->debug_utils.callbacks)) { 153 VkDebugUtilsMessengerCallbackDataEXT cb_data = { 154 .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT, 155 .pMessageIdName = message_idname, 156 .messageIdNumber = 0, 157 .pMessage = message, 158 }; 159 160 VkDebugUtilsObjectNameInfoEXT *object_name_infos = 161 ralloc_array(NULL, VkDebugUtilsObjectNameInfoEXT, object_count); 162 163 ASSERTED int cmdbuf_n = 0, queue_n = 0; 164 for (int i = 0; i < object_count; i++) { 165 struct vk_object_base *base = objects[i]; 166 assert(base->client_visible); 167 168 switch (base->type) { 169 case VK_OBJECT_TYPE_COMMAND_BUFFER: { 170 /* We allow at most one command buffer to be submitted at a time */ 171 assert(++cmdbuf_n <= 1); 172 struct vk_command_buffer *cmd_buffer = 173 (struct vk_command_buffer *)base; 174 if (cmd_buffer->labels.size > 0) { 175 cb_data.cmdBufLabelCount = util_dynarray_num_elements( 176 &cmd_buffer->labels, VkDebugUtilsLabelEXT); 177 cb_data.pCmdBufLabels = cmd_buffer->labels.data; 178 } 179 break; 180 } 181 182 case VK_OBJECT_TYPE_QUEUE: { 183 /* We allow at most one queue to be submitted at a time */ 184 assert(++queue_n <= 1); 185 struct vk_queue *queue = (struct vk_queue *)base; 186 if (queue->labels.size > 0) { 187 cb_data.queueLabelCount = 188 util_dynarray_num_elements(&queue->labels, VkDebugUtilsLabelEXT); 189 cb_data.pQueueLabels = queue->labels.data; 190 } 191 break; 192 } 193 default: 194 break; 195 } 196 197 object_name_infos[i] = (VkDebugUtilsObjectNameInfoEXT){ 198 .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, 199 .pNext = NULL, 200 .objectType = base->type, 201 .objectHandle = (uint64_t)(uintptr_t)base, 202 .pObjectName = base->object_name, 203 }; 204 } 205 cb_data.objectCount = object_count; 206 cb_data.pObjects = object_name_infos; 207 208 vk_debug_message(instance, severity, types, &cb_data); 209 210 ralloc_free(object_name_infos); 211 } 212 213 /* If VK_EXT_debug_report callbacks also have been set up, forward 214 * the message there as well */ 215 if (!list_is_empty(&instance->debug_report.callbacks)) { 216 VkDebugReportFlagsEXT flags = 0; 217 218 switch (severity) { 219 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: 220 flags |= VK_DEBUG_REPORT_DEBUG_BIT_EXT; 221 break; 222 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: 223 flags |= VK_DEBUG_REPORT_INFORMATION_BIT_EXT; 224 break; 225 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: 226 if (types & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) 227 flags |= VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; 228 else 229 flags |= VK_DEBUG_REPORT_WARNING_BIT_EXT; 230 break; 231 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: 232 flags |= VK_DEBUG_REPORT_ERROR_BIT_EXT; 233 break; 234 default: 235 unreachable("Invalid debug message severity"); 236 break; 237 } 238 239 /* VK_EXT_debug_report-provided callback accepts only one object 240 * related to the message. Since they are given to us in 241 * decreasing order of importance, we're forwarding the first 242 * one. 243 */ 244 vk_debug_report(instance, flags, object_count ? objects[0] : NULL, 0, 245 0, message_idname, message); 246 } 247 248 ralloc_free(message); 249 ralloc_free(message_idname); 250} 251 252static struct vk_object_base * 253vk_object_for_error(struct vk_object_base *obj, VkResult error) 254{ 255 if (obj == NULL) 256 return NULL; 257 258 switch (error) { 259 case VK_ERROR_OUT_OF_HOST_MEMORY: 260 case VK_ERROR_LAYER_NOT_PRESENT: 261 case VK_ERROR_EXTENSION_NOT_PRESENT: 262 case VK_ERROR_UNKNOWN: 263 return &vk_object_to_instance(obj)->base; 264 case VK_ERROR_FEATURE_NOT_PRESENT: 265 return &vk_object_to_physical_device(obj)->base; 266 case VK_ERROR_OUT_OF_DEVICE_MEMORY: 267 case VK_ERROR_MEMORY_MAP_FAILED: 268 case VK_ERROR_TOO_MANY_OBJECTS: 269 return &vk_object_to_device(obj)->base; 270 default: 271 return obj; 272 } 273} 274 275VkResult 276__vk_errorv(const void *_obj, VkResult error, 277 const char *file, int line, 278 const char *format, va_list va) 279{ 280 struct vk_object_base *object = (struct vk_object_base *)_obj; 281 struct vk_instance *instance = vk_object_to_instance(object); 282 object = vk_object_for_error(object, error); 283 284 /* If object->client_visible isn't set then the object hasn't been fully 285 * constructed and we shouldn't hand it back to the client. This typically 286 * happens if an error is thrown during object construction. This is safe 287 * to do as long as vk_object_base_init() has already been called. 288 */ 289 if (object && !object->client_visible) 290 object = NULL; 291 292 const char *error_str = vk_Result_to_str(error); 293 294 if (format) { 295 char *message = ralloc_vasprintf(NULL, format, va); 296 297 if (object) { 298 __vk_log(VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, 299 VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, 300 VK_LOG_OBJS(object), file, line, 301 "%s (%s)", message, error_str); 302 } else { 303 __vk_log(VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, 304 VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, 305 VK_LOG_NO_OBJS(instance), file, line, 306 "%s (%s)", message, error_str); 307 } 308 309 ralloc_free(message); 310 } else { 311 if (object) { 312 __vk_log(VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, 313 VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, 314 VK_LOG_OBJS(object), file, line, 315 "%s", error_str); 316 } else { 317 __vk_log(VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, 318 VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, 319 VK_LOG_NO_OBJS(instance), file, line, 320 "%s", error_str); 321 } 322 } 323 324 return error; 325} 326 327VkResult 328__vk_errorf(const void *_obj, VkResult error, 329 const char *file, int line, 330 const char *format, ...) 331{ 332 va_list va; 333 334 va_start(va, format); 335 VkResult result = __vk_errorv(_obj, error, file, line, format, va); 336 va_end(va); 337 338 return result; 339} 340