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