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 for (unsigned i = 0; i < object_count; i++) { 94 if (unlikely(objects[i] == NULL)) { 95 mesa_logw("vk_log*() called with NULL object\n"); 96 continue; 97 } 98 99 if (unlikely(!objects[i]->client_visible)) { 100 mesa_logw("vk_log*() called with client-invisible object %p " 101 "of type %s", objects[i], 102 vk_ObjectType_to_str(objects[i]->type)); 103 } 104 105 if (!instance) { 106 instance = vk_object_to_instance(objects[i]); 107 assert(instance->base.client_visible); 108 } else { 109 assert(vk_object_to_instance(objects[i]) == instance); 110 } 111 break; 112 } 113 } 114 115#ifndef DEBUG 116 if (unlikely(!instance) || 117 (likely(list_is_empty(&instance->debug_utils.callbacks)) && 118 likely(list_is_empty(&instance->debug_report.callbacks)))) 119 return; 120#endif 121 122 va_list va; 123 char *message = NULL; 124 125 va_start(va, format); 126 message = ralloc_vasprintf(NULL, format, va); 127 va_end(va); 128 129 char *message_idname = ralloc_asprintf(NULL, "%s:%d", file, line); 130 131#if DEBUG 132 switch (severity) { 133 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: 134 mesa_logd("%s: %s", message_idname, message); 135 break; 136 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: 137 mesa_logi("%s: %s", message_idname, message); 138 break; 139 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: 140 if (types & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) 141 mesa_logw("%s: PERF: %s", message_idname, message); 142 else 143 mesa_logw("%s: %s", message_idname, message); 144 break; 145 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: 146 mesa_loge("%s: %s", message_idname, message); 147 break; 148 default: 149 unreachable("Invalid debug message severity"); 150 break; 151 } 152 153 if (!instance) { 154 ralloc_free(message); 155 ralloc_free(message_idname); 156 return; 157 } 158#endif 159 160 if (!instance->base.client_visible) { 161 vk_debug_message_instance(instance, severity, types, 162 message_idname, 0, message); 163 ralloc_free(message); 164 ralloc_free(message_idname); 165 return; 166 } 167 168 /* If VK_EXT_debug_utils messengers have been set up, form the 169 * message */ 170 if (!list_is_empty(&instance->debug_utils.callbacks)) { 171 VkDebugUtilsMessengerCallbackDataEXT cb_data = { 172 .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT, 173 .pMessageIdName = message_idname, 174 .messageIdNumber = 0, 175 .pMessage = message, 176 }; 177 178 VkDebugUtilsObjectNameInfoEXT *object_name_infos = 179 ralloc_array(NULL, VkDebugUtilsObjectNameInfoEXT, object_count); 180 181 ASSERTED int cmdbuf_n = 0, queue_n = 0, obj_n = 0; 182 for (int i = 0; i < object_count; i++) { 183 struct vk_object_base *base = objects[i]; 184 if (base == NULL || !base->client_visible) 185 continue; 186 187 switch (base->type) { 188 case VK_OBJECT_TYPE_COMMAND_BUFFER: { 189 /* We allow at most one command buffer to be submitted at a time */ 190 assert(++cmdbuf_n <= 1); 191 struct vk_command_buffer *cmd_buffer = 192 (struct vk_command_buffer *)base; 193 if (cmd_buffer->labels.size > 0) { 194 cb_data.cmdBufLabelCount = util_dynarray_num_elements( 195 &cmd_buffer->labels, VkDebugUtilsLabelEXT); 196 cb_data.pCmdBufLabels = cmd_buffer->labels.data; 197 } 198 break; 199 } 200 201 case VK_OBJECT_TYPE_QUEUE: { 202 /* We allow at most one queue to be submitted at a time */ 203 assert(++queue_n <= 1); 204 struct vk_queue *queue = (struct vk_queue *)base; 205 if (queue->labels.size > 0) { 206 cb_data.queueLabelCount = 207 util_dynarray_num_elements(&queue->labels, VkDebugUtilsLabelEXT); 208 cb_data.pQueueLabels = queue->labels.data; 209 } 210 break; 211 } 212 default: 213 break; 214 } 215 216 object_name_infos[obj_n++] = (VkDebugUtilsObjectNameInfoEXT){ 217 .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, 218 .pNext = NULL, 219 .objectType = base->type, 220 .objectHandle = (uint64_t)(uintptr_t)base, 221 .pObjectName = base->object_name, 222 }; 223 } 224 cb_data.objectCount = obj_n; 225 cb_data.pObjects = object_name_infos; 226 227 vk_debug_message(instance, severity, types, &cb_data); 228 229 ralloc_free(object_name_infos); 230 } 231 232 /* If VK_EXT_debug_report callbacks also have been set up, forward 233 * the message there as well */ 234 if (!list_is_empty(&instance->debug_report.callbacks)) { 235 VkDebugReportFlagsEXT flags = 0; 236 237 switch (severity) { 238 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: 239 flags |= VK_DEBUG_REPORT_DEBUG_BIT_EXT; 240 break; 241 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: 242 flags |= VK_DEBUG_REPORT_INFORMATION_BIT_EXT; 243 break; 244 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: 245 if (types & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) 246 flags |= VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; 247 else 248 flags |= VK_DEBUG_REPORT_WARNING_BIT_EXT; 249 break; 250 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: 251 flags |= VK_DEBUG_REPORT_ERROR_BIT_EXT; 252 break; 253 default: 254 unreachable("Invalid debug message severity"); 255 break; 256 } 257 258 /* VK_EXT_debug_report-provided callback accepts only one object 259 * related to the message. Since they are given to us in 260 * decreasing order of importance, we're forwarding the first 261 * one. 262 */ 263 vk_debug_report(instance, flags, object_count ? objects[0] : NULL, 0, 264 0, message_idname, message); 265 } 266 267 ralloc_free(message); 268 ralloc_free(message_idname); 269} 270 271static struct vk_object_base * 272vk_object_for_error(struct vk_object_base *obj, VkResult error) 273{ 274 if (obj == NULL) 275 return NULL; 276 277 switch (error) { 278 case VK_ERROR_OUT_OF_HOST_MEMORY: 279 case VK_ERROR_LAYER_NOT_PRESENT: 280 case VK_ERROR_EXTENSION_NOT_PRESENT: 281 case VK_ERROR_UNKNOWN: 282 return &vk_object_to_instance(obj)->base; 283 case VK_ERROR_FEATURE_NOT_PRESENT: 284 return &vk_object_to_physical_device(obj)->base; 285 case VK_ERROR_OUT_OF_DEVICE_MEMORY: 286 case VK_ERROR_MEMORY_MAP_FAILED: 287 case VK_ERROR_TOO_MANY_OBJECTS: 288 return &vk_object_to_device(obj)->base; 289 default: 290 return obj; 291 } 292} 293 294VkResult 295__vk_errorv(const void *_obj, VkResult error, 296 const char *file, int line, 297 const char *format, va_list va) 298{ 299 struct vk_object_base *object = (struct vk_object_base *)_obj; 300 struct vk_instance *instance = vk_object_to_instance(object); 301 object = vk_object_for_error(object, error); 302 303 /* If object->client_visible isn't set then the object hasn't been fully 304 * constructed and we shouldn't hand it back to the client. This typically 305 * happens if an error is thrown during object construction. This is safe 306 * to do as long as vk_object_base_init() has already been called. 307 */ 308 if (object && !object->client_visible) 309 object = NULL; 310 311 const char *error_str = vk_Result_to_str(error); 312 313 if (format) { 314 char *message = ralloc_vasprintf(NULL, format, va); 315 316 if (object) { 317 __vk_log(VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, 318 VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, 319 VK_LOG_OBJS(object), file, line, 320 "%s (%s)", message, error_str); 321 } else { 322 __vk_log(VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, 323 VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, 324 VK_LOG_NO_OBJS(instance), file, line, 325 "%s (%s)", message, error_str); 326 } 327 328 ralloc_free(message); 329 } else { 330 if (object) { 331 __vk_log(VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, 332 VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, 333 VK_LOG_OBJS(object), file, line, 334 "%s", error_str); 335 } else { 336 __vk_log(VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, 337 VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, 338 VK_LOG_NO_OBJS(instance), file, line, 339 "%s", error_str); 340 } 341 } 342 343 return error; 344} 345 346VkResult 347__vk_errorf(const void *_obj, VkResult error, 348 const char *file, int line, 349 const char *format, ...) 350{ 351 va_list va; 352 353 va_start(va, format); 354 VkResult result = __vk_errorv(_obj, error, file, line, format, va); 355 va_end(va); 356 357 return result; 358} 359