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_debug_utils.h"
25
26 #include "vk_common_entrypoints.h"
27 #include "vk_command_buffer.h"
28 #include "vk_device.h"
29 #include "vk_queue.h"
30 #include "vk_object.h"
31 #include "vk_alloc.h"
32 #include "vk_util.h"
33 #include "stdarg.h"
34 #include "u_dynarray.h"
35
36 void
vk_debug_message(struct vk_instance * instance,VkDebugUtilsMessageSeverityFlagBitsEXT severity,VkDebugUtilsMessageTypeFlagsEXT types,const VkDebugUtilsMessengerCallbackDataEXT * pCallbackData)37 vk_debug_message(struct vk_instance *instance,
38 VkDebugUtilsMessageSeverityFlagBitsEXT severity,
39 VkDebugUtilsMessageTypeFlagsEXT types,
40 const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData)
41 {
42 mtx_lock(&instance->debug_utils.callbacks_mutex);
43
44 list_for_each_entry(struct vk_debug_utils_messenger, messenger,
45 &instance->debug_utils.callbacks, link) {
46 if ((messenger->severity & severity) &&
47 (messenger->type & types))
48 messenger->callback(severity, types, pCallbackData, messenger->data);
49 }
50
51 mtx_unlock(&instance->debug_utils.callbacks_mutex);
52 }
53
54 /* This function intended to be used by the drivers to report a
55 * message to the special messenger, provided in the pNext chain while
56 * creating an instance. It's only meant to be used during
57 * vkCreateInstance or vkDestroyInstance calls.
58 */
59 void
vk_debug_message_instance(struct vk_instance * instance,VkDebugUtilsMessageSeverityFlagBitsEXT severity,VkDebugUtilsMessageTypeFlagsEXT types,const char * pMessageIdName,int32_t messageIdNumber,const char * pMessage)60 vk_debug_message_instance(struct vk_instance *instance,
61 VkDebugUtilsMessageSeverityFlagBitsEXT severity,
62 VkDebugUtilsMessageTypeFlagsEXT types,
63 const char *pMessageIdName,
64 int32_t messageIdNumber,
65 const char *pMessage)
66 {
67 if (list_is_empty(&instance->debug_utils.instance_callbacks))
68 return;
69
70 const VkDebugUtilsMessengerCallbackDataEXT cbData = {
71 .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT,
72 .pMessageIdName = pMessageIdName,
73 .messageIdNumber = messageIdNumber,
74 .pMessage = pMessage,
75 };
76
77 list_for_each_entry(struct vk_debug_utils_messenger, messenger,
78 &instance->debug_utils.instance_callbacks, link) {
79 if ((messenger->severity & severity) &&
80 (messenger->type & types))
81 messenger->callback(severity, types, &cbData, messenger->data);
82 }
83 }
84
85 VKAPI_ATTR VkResult VKAPI_CALL
vk_common_CreateDebugUtilsMessengerEXT(VkInstance _instance,const VkDebugUtilsMessengerCreateInfoEXT * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDebugUtilsMessengerEXT * pMessenger)86 vk_common_CreateDebugUtilsMessengerEXT(
87 VkInstance _instance,
88 const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
89 const VkAllocationCallbacks *pAllocator,
90 VkDebugUtilsMessengerEXT *pMessenger)
91 {
92 VK_FROM_HANDLE(vk_instance, instance, _instance);
93
94 struct vk_debug_utils_messenger *messenger =
95 vk_alloc2(&instance->alloc, pAllocator,
96 sizeof(struct vk_debug_utils_messenger), 8,
97 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
98
99 if (!messenger)
100 return VK_ERROR_OUT_OF_HOST_MEMORY;
101
102 if (pAllocator)
103 messenger->alloc = *pAllocator;
104 else
105 messenger->alloc = instance->alloc;
106
107 vk_object_base_init(NULL, &messenger->base,
108 VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT);
109
110 messenger->severity = pCreateInfo->messageSeverity;
111 messenger->type = pCreateInfo->messageType;
112 messenger->callback = pCreateInfo->pfnUserCallback;
113 messenger->data = pCreateInfo->pUserData;
114
115 mtx_lock(&instance->debug_utils.callbacks_mutex);
116 list_addtail(&messenger->link, &instance->debug_utils.callbacks);
117 mtx_unlock(&instance->debug_utils.callbacks_mutex);
118
119 *pMessenger = vk_debug_utils_messenger_to_handle(messenger);
120
121 return VK_SUCCESS;
122 }
123
124 VKAPI_ATTR void VKAPI_CALL
vk_common_SubmitDebugUtilsMessageEXT(VkInstance _instance,VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,VkDebugUtilsMessageTypeFlagsEXT messageTypes,const VkDebugUtilsMessengerCallbackDataEXT * pCallbackData)125 vk_common_SubmitDebugUtilsMessageEXT(
126 VkInstance _instance,
127 VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
128 VkDebugUtilsMessageTypeFlagsEXT messageTypes,
129 const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData)
130 {
131 VK_FROM_HANDLE(vk_instance, instance, _instance);
132
133 vk_debug_message(instance, messageSeverity, messageTypes, pCallbackData);
134 }
135
136 VKAPI_ATTR void VKAPI_CALL
vk_common_DestroyDebugUtilsMessengerEXT(VkInstance _instance,VkDebugUtilsMessengerEXT _messenger,const VkAllocationCallbacks * pAllocator)137 vk_common_DestroyDebugUtilsMessengerEXT(
138 VkInstance _instance,
139 VkDebugUtilsMessengerEXT _messenger,
140 const VkAllocationCallbacks *pAllocator)
141 {
142 VK_FROM_HANDLE(vk_instance, instance, _instance);
143 VK_FROM_HANDLE(vk_debug_utils_messenger, messenger, _messenger);
144
145 if (messenger == NULL)
146 return;
147
148 mtx_lock(&instance->debug_utils.callbacks_mutex);
149 list_del(&messenger->link);
150 mtx_unlock(&instance->debug_utils.callbacks_mutex);
151
152 vk_object_base_finish(&messenger->base);
153 vk_free2(&instance->alloc, pAllocator, messenger);
154 }
155
156 VKAPI_ATTR VkResult VKAPI_CALL
vk_common_SetDebugUtilsObjectNameEXT(VkDevice _device,const VkDebugUtilsObjectNameInfoEXT * pNameInfo)157 vk_common_SetDebugUtilsObjectNameEXT(
158 VkDevice _device,
159 const VkDebugUtilsObjectNameInfoEXT *pNameInfo)
160 {
161 VK_FROM_HANDLE(vk_device, device, _device);
162 struct vk_object_base *object =
163 vk_object_base_from_u64_handle(pNameInfo->objectHandle,
164 pNameInfo->objectType);
165
166 if (object->object_name) {
167 vk_free(&device->alloc, object->object_name);
168 object->object_name = NULL;
169 }
170 object->object_name = vk_strdup(&device->alloc, pNameInfo->pObjectName,
171 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
172 if (!object->object_name)
173 return VK_ERROR_OUT_OF_HOST_MEMORY;
174
175 return VK_SUCCESS;
176 }
177
178 VKAPI_ATTR VkResult VKAPI_CALL
vk_common_SetDebugUtilsObjectTagEXT(VkDevice _device,const VkDebugUtilsObjectTagInfoEXT * pTagInfo)179 vk_common_SetDebugUtilsObjectTagEXT(
180 VkDevice _device,
181 const VkDebugUtilsObjectTagInfoEXT *pTagInfo)
182 {
183 /* no-op */
184 return VK_SUCCESS;
185 }
186
187 VKAPI_ATTR void VKAPI_CALL
vk_common_CmdBeginDebugUtilsLabelEXT(VkCommandBuffer _commandBuffer,const VkDebugUtilsLabelEXT * pLabelInfo)188 vk_common_CmdBeginDebugUtilsLabelEXT(
189 VkCommandBuffer _commandBuffer,
190 const VkDebugUtilsLabelEXT *pLabelInfo)
191 {
192 VK_FROM_HANDLE(vk_command_buffer, command_buffer, _commandBuffer);
193
194 /* If the latest label was submitted by CmdInsertDebugUtilsLabelEXT, we
195 * should remove it first.
196 */
197 if (!command_buffer->region_begin)
198 (void)util_dynarray_pop(&command_buffer->labels, VkDebugUtilsLabelEXT);
199
200 util_dynarray_append(&command_buffer->labels, VkDebugUtilsLabelEXT,
201 *pLabelInfo);
202 command_buffer->region_begin = true;
203 }
204
205 VKAPI_ATTR void VKAPI_CALL
vk_common_CmdEndDebugUtilsLabelEXT(VkCommandBuffer _commandBuffer)206 vk_common_CmdEndDebugUtilsLabelEXT(VkCommandBuffer _commandBuffer)
207 {
208 VK_FROM_HANDLE(vk_command_buffer, command_buffer, _commandBuffer);
209
210 /* If the latest label was submitted by CmdInsertDebugUtilsLabelEXT, we
211 * should remove it first.
212 */
213 if (!command_buffer->region_begin)
214 (void)util_dynarray_pop(&command_buffer->labels, VkDebugUtilsLabelEXT);
215
216 (void)util_dynarray_pop(&command_buffer->labels, VkDebugUtilsLabelEXT);
217 command_buffer->region_begin = true;
218 }
219
220 VKAPI_ATTR void VKAPI_CALL
vk_common_CmdInsertDebugUtilsLabelEXT(VkCommandBuffer _commandBuffer,const VkDebugUtilsLabelEXT * pLabelInfo)221 vk_common_CmdInsertDebugUtilsLabelEXT(
222 VkCommandBuffer _commandBuffer,
223 const VkDebugUtilsLabelEXT *pLabelInfo)
224 {
225 VK_FROM_HANDLE(vk_command_buffer, command_buffer, _commandBuffer);
226
227 /* If the latest label was submitted by CmdInsertDebugUtilsLabelEXT, we
228 * should remove it first.
229 */
230 if (!command_buffer->region_begin)
231 (void)util_dynarray_pop(&command_buffer->labels, VkDebugUtilsLabelEXT);
232
233 util_dynarray_append(&command_buffer->labels, VkDebugUtilsLabelEXT,
234 *pLabelInfo);
235 command_buffer->region_begin = false;
236 }
237
238 VKAPI_ATTR void VKAPI_CALL
vk_common_QueueBeginDebugUtilsLabelEXT(VkQueue _queue,const VkDebugUtilsLabelEXT * pLabelInfo)239 vk_common_QueueBeginDebugUtilsLabelEXT(
240 VkQueue _queue,
241 const VkDebugUtilsLabelEXT *pLabelInfo)
242 {
243 VK_FROM_HANDLE(vk_queue, queue, _queue);
244
245 /* If the latest label was submitted by QueueInsertDebugUtilsLabelEXT, we
246 * should remove it first.
247 */
248 if (!queue->region_begin)
249 (void)util_dynarray_pop(&queue->labels, VkDebugUtilsLabelEXT);
250
251 util_dynarray_append(&queue->labels, VkDebugUtilsLabelEXT, *pLabelInfo);
252 queue->region_begin = true;
253 }
254
255 VKAPI_ATTR void VKAPI_CALL
vk_common_QueueEndDebugUtilsLabelEXT(VkQueue _queue)256 vk_common_QueueEndDebugUtilsLabelEXT(VkQueue _queue)
257 {
258 VK_FROM_HANDLE(vk_queue, queue, _queue);
259
260 /* If the latest label was submitted by QueueInsertDebugUtilsLabelEXT, we
261 * should remove it first.
262 */
263 if (!queue->region_begin)
264 (void)util_dynarray_pop(&queue->labels, VkDebugUtilsLabelEXT);
265
266 (void)util_dynarray_pop(&queue->labels, VkDebugUtilsLabelEXT);
267 queue->region_begin = true;
268 }
269
270 VKAPI_ATTR void VKAPI_CALL
vk_common_QueueInsertDebugUtilsLabelEXT(VkQueue _queue,const VkDebugUtilsLabelEXT * pLabelInfo)271 vk_common_QueueInsertDebugUtilsLabelEXT(
272 VkQueue _queue,
273 const VkDebugUtilsLabelEXT *pLabelInfo)
274 {
275 VK_FROM_HANDLE(vk_queue, queue, _queue);
276
277 /* If the latest label was submitted by QueueInsertDebugUtilsLabelEXT, we
278 * should remove it first.
279 */
280 if (!queue->region_begin)
281 (void)util_dynarray_pop(&queue->labels, VkDebugUtilsLabelEXT);
282
283 util_dynarray_append(&queue->labels, VkDebugUtilsLabelEXT, *pLabelInfo);
284 queue->region_begin = false;
285 }
286