• 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_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 
38 static struct vk_device *
vk_object_to_device(struct vk_object_base * obj)39 vk_object_to_device(struct vk_object_base *obj)
40 {
41    assert(obj->device);
42    return obj->device;
43 }
44 
45 static struct vk_physical_device *
vk_object_to_physical_device(struct vk_object_base * obj)46 vk_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 
64 static struct vk_instance *
vk_object_to_instance(struct vk_object_base * obj)65 vk_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 
77 void
__vk_log_impl(VkDebugUtilsMessageSeverityFlagBitsEXT severity,VkDebugUtilsMessageTypeFlagsEXT types,int object_count,const void ** objects_or_instance,const char * file,int line,const char * format,...)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 
271 static struct vk_object_base *
vk_object_for_error(struct vk_object_base * obj,VkResult error)272 vk_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 
294 VkResult
__vk_errorv(const void * _obj,VkResult error,const char * file,int line,const char * format,va_list va)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 
346 VkResult
__vk_errorf(const void * _obj,VkResult error,const char * file,int line,const char * format,...)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