blob: c4bfe7218f437dae1639ae301d1216036b53d4cb [file] [log] [blame]
Mark Younge3e9b562017-11-09 10:37:04 -07001/*
2 * Copyright (c) 2015-2017 The Khronos Group Inc.
3 * Copyright (c) 2015-2017 Valve Corporation
4 * Copyright (c) 2015-2017 LunarG, Inc.
5 * Copyright (C) 2015-2016 Google Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
20 * Author: Jon Ashburn <jon@LunarG.com>
21 * Author: Mark Young <marky@lunarg.com>
22 *
23 */
24
Tom Andersona8358802018-07-25 17:10:16 -070025#ifndef _GNU_SOURCE
Mark Younge3e9b562017-11-09 10:37:04 -070026#define _GNU_SOURCE
Tom Andersona8358802018-07-25 17:10:16 -070027#endif
Mark Younge3e9b562017-11-09 10:37:04 -070028#include <stdio.h>
29#include <string.h>
30#include <stdlib.h>
31#include <inttypes.h>
32#ifndef WIN32
33#include <signal.h>
34#else
35#endif
36#include "vk_loader_platform.h"
37#include "debug_utils.h"
38#include "vulkan/vk_layer.h"
39#include "vk_object_types.h"
40
41// VK_EXT_debug_report related items
42
43VkResult util_CreateDebugUtilsMessenger(struct loader_instance *inst, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
44 const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerEXT messenger) {
45 VkLayerDbgFunctionNode *pNewDbgFuncNode = NULL;
46
47#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
48 {
49#else
50 if (pAllocator != NULL) {
51 pNewDbgFuncNode = (VkLayerDbgFunctionNode *)pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(VkLayerDbgFunctionNode),
52 sizeof(int *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
53 } else {
54#endif
55 pNewDbgFuncNode = (VkLayerDbgFunctionNode *)loader_instance_heap_alloc(inst, sizeof(VkLayerDbgFunctionNode),
56 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
57 }
58 if (!pNewDbgFuncNode) {
59 return VK_ERROR_OUT_OF_HOST_MEMORY;
60 }
61 memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
62
63 pNewDbgFuncNode->is_messenger = true;
64 pNewDbgFuncNode->messenger.messenger = messenger;
65 pNewDbgFuncNode->messenger.pfnUserCallback = pCreateInfo->pfnUserCallback;
66 pNewDbgFuncNode->messenger.messageSeverity = pCreateInfo->messageSeverity;
67 pNewDbgFuncNode->messenger.messageType = pCreateInfo->messageType;
68 pNewDbgFuncNode->pUserData = pCreateInfo->pUserData;
69 pNewDbgFuncNode->pNext = inst->DbgFunctionHead;
70 inst->DbgFunctionHead = pNewDbgFuncNode;
71
72 return VK_SUCCESS;
73}
74
75static VKAPI_ATTR VkResult VKAPI_CALL
76debug_utils_CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
77 const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerEXT *pMessenger) {
78 struct loader_instance *inst = loader_get_instance(instance);
79 loader_platform_thread_lock_mutex(&loader_lock);
80 VkResult result = inst->disp->layer_inst_disp.CreateDebugUtilsMessengerEXT(instance, pCreateInfo, pAllocator, pMessenger);
81 loader_platform_thread_unlock_mutex(&loader_lock);
82 return result;
83}
84
85VkBool32 util_SubmitDebugUtilsMessageEXT(const struct loader_instance *inst, VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
86 VkDebugUtilsMessageTypeFlagsEXT messageTypes,
87 const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData) {
88 VkBool32 bail = false;
89
Mark Youngdad818e2018-10-29 11:09:55 -060090 if (NULL != pCallbackData) {
Mark Younge3e9b562017-11-09 10:37:04 -070091 VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead;
Mark Youngdad818e2018-10-29 11:09:55 -060092 VkDebugReportObjectTypeEXT object_type = VK_OBJECT_TYPE_UNKNOWN;
Mark Younge3e9b562017-11-09 10:37:04 -070093 VkDebugReportFlagsEXT object_flags = 0;
Mark Youngdad818e2018-10-29 11:09:55 -060094 uint64_t object_handle = 0;
Mark Younge3e9b562017-11-09 10:37:04 -070095
96 debug_utils_AnnotFlagsToReportFlags(messageSeverity, messageTypes, &object_flags);
Mark Youngdad818e2018-10-29 11:09:55 -060097 if (0 < pCallbackData->objectCount) {
98 debug_utils_AnnotObjectToDebugReportObject(pCallbackData->pObjects, &object_type, &object_handle);
99 }
Mark Younge3e9b562017-11-09 10:37:04 -0700100
101 while (pTrav) {
102 if (pTrav->is_messenger && (pTrav->messenger.messageSeverity & messageSeverity) &&
103 (pTrav->messenger.messageType & messageTypes)) {
104 if (pTrav->messenger.pfnUserCallback(messageSeverity, messageTypes, pCallbackData, pTrav->pUserData)) {
105 bail = true;
106 }
107 }
108 if (!pTrav->is_messenger && pTrav->report.msgFlags & object_flags) {
109 if (pTrav->report.pfnMsgCallback(object_flags, object_type, object_handle, 0, pCallbackData->messageIdNumber,
110 pCallbackData->pMessageIdName, pCallbackData->pMessage, pTrav->pUserData)) {
111 bail = true;
112 }
113 }
114
115 pTrav = pTrav->pNext;
116 }
117 }
118
119 return bail;
120}
121
122void util_DestroyDebugUtilsMessenger(struct loader_instance *inst, VkDebugUtilsMessengerEXT messenger,
123 const VkAllocationCallbacks *pAllocator) {
124 VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead;
125 VkLayerDbgFunctionNode *pPrev = pTrav;
126
127 while (pTrav) {
128 if (pTrav->is_messenger && pTrav->messenger.messenger == messenger) {
129 pPrev->pNext = pTrav->pNext;
130 if (inst->DbgFunctionHead == pTrav) inst->DbgFunctionHead = pTrav->pNext;
131#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
132 {
133#else
134 if (pAllocator != NULL) {
135 pAllocator->pfnFree(pAllocator->pUserData, pTrav);
136 } else {
137#endif
138 loader_instance_heap_free(inst, pTrav);
139 }
140 break;
141 }
142 pPrev = pTrav;
143 pTrav = pTrav->pNext;
144 }
145}
146
147// This utility (used by vkInstanceCreateInfo(), looks at a pNext chain. It
148// counts any VkDebugUtilsMessengerCreateInfoEXT structs that it finds. It
149// then allocates array that can hold that many structs, as well as that many
150// VkDebugUtilsMessengerEXT handles. It then copies each
151// VkDebugUtilsMessengerCreateInfoEXT, and initializes each handle.
152VkResult util_CopyDebugUtilsMessengerCreateInfos(const void *pChain, const VkAllocationCallbacks *pAllocator,
153 uint32_t *num_messengers, VkDebugUtilsMessengerCreateInfoEXT **infos,
154 VkDebugUtilsMessengerEXT **messengers) {
155 uint32_t n = *num_messengers = 0;
156 VkDebugUtilsMessengerCreateInfoEXT *pInfos = NULL;
157 VkDebugUtilsMessengerEXT *pMessengers = NULL;
158
159 const void *pNext = pChain;
160 while (pNext) {
161 // 1st, count the number VkDebugUtilsMessengerCreateInfoEXT:
162 if (((VkDebugUtilsMessengerCreateInfoEXT *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
163 n++;
164 }
165 pNext = (void *)((VkDebugUtilsMessengerCreateInfoEXT *)pNext)->pNext;
166 }
167 if (n == 0) {
168 return VK_SUCCESS;
169 }
170
171// 2nd, allocate memory for each VkDebugUtilsMessengerCreateInfoEXT:
172#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
173 {
174#else
175 if (pAllocator != NULL) {
176 pInfos = *infos = ((VkDebugUtilsMessengerCreateInfoEXT *)pAllocator->pfnAllocation(
177 pAllocator->pUserData, n * sizeof(VkDebugUtilsMessengerCreateInfoEXT), sizeof(void *),
178 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
179 } else {
180#endif
181 pInfos = *infos = ((VkDebugUtilsMessengerCreateInfoEXT *)malloc(n * sizeof(VkDebugUtilsMessengerCreateInfoEXT)));
182 }
183 if (!pInfos) {
184 return VK_ERROR_OUT_OF_HOST_MEMORY;
185 }
186// 3rd, allocate memory for a unique handle for each callback:
187#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
188 {
189#else
190 if (pAllocator != NULL) {
191 pMessengers = *messengers = ((VkDebugUtilsMessengerEXT *)pAllocator->pfnAllocation(
192 pAllocator->pUserData, n * sizeof(VkDebugUtilsMessengerEXT), sizeof(void *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
193 if (NULL == pMessengers) {
194 pAllocator->pfnFree(pAllocator->pUserData, pInfos);
195 return VK_ERROR_OUT_OF_HOST_MEMORY;
196 }
197 } else {
198#endif
199 pMessengers = *messengers = ((VkDebugUtilsMessengerEXT *)malloc(n * sizeof(VkDebugUtilsMessengerEXT)));
200 if (NULL == pMessengers) {
201 free(pInfos);
202 return VK_ERROR_OUT_OF_HOST_MEMORY;
203 }
204 }
205 // 4th, copy each VkDebugUtilsMessengerCreateInfoEXT for use by
206 // vkDestroyInstance, and assign a unique handle to each messenger (just
207 // use the address of the copied VkDebugUtilsMessengerCreateInfoEXT):
208 pNext = pChain;
209 while (pNext) {
210 if (((VkInstanceCreateInfo *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
211 memcpy(pInfos, pNext, sizeof(VkDebugUtilsMessengerCreateInfoEXT));
212 *pMessengers++ = (VkDebugUtilsMessengerEXT)(uintptr_t)pInfos++;
213 }
214 pNext = (void *)((VkInstanceCreateInfo *)pNext)->pNext;
215 }
216
217 *num_messengers = n;
218 return VK_SUCCESS;
219}
220
221void util_FreeDebugUtilsMessengerCreateInfos(const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerCreateInfoEXT *infos,
222 VkDebugUtilsMessengerEXT *messengers) {
223#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
224 {
225#else
226 if (pAllocator != NULL) {
227 pAllocator->pfnFree(pAllocator->pUserData, infos);
228 pAllocator->pfnFree(pAllocator->pUserData, messengers);
229 } else {
230#endif
231 free(infos);
232 free(messengers);
233 }
234}
235
236VkResult util_CreateDebugUtilsMessengers(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator,
237 uint32_t num_messengers, VkDebugUtilsMessengerCreateInfoEXT *infos,
238 VkDebugUtilsMessengerEXT *messengers) {
239 VkResult rtn = VK_SUCCESS;
240 for (uint32_t i = 0; i < num_messengers; i++) {
241 rtn = util_CreateDebugUtilsMessenger(inst, &infos[i], pAllocator, messengers[i]);
242 if (rtn != VK_SUCCESS) {
243 for (uint32_t j = 0; j < i; j++) {
244 util_DestroyDebugUtilsMessenger(inst, messengers[j], pAllocator);
245 }
246 return rtn;
247 }
248 }
249 return rtn;
250}
251
252void util_DestroyDebugUtilsMessengers(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator,
253 uint32_t num_messengers, VkDebugUtilsMessengerEXT *messengers) {
254 for (uint32_t i = 0; i < num_messengers; i++) {
255 util_DestroyDebugUtilsMessenger(inst, messengers[i], pAllocator);
256 }
257}
258
259static VKAPI_ATTR void VKAPI_CALL debug_utils_SubmitDebugUtilsMessageEXT(
260 VkInstance instance, VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageTypes,
261 const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData) {
262 struct loader_instance *inst = loader_get_instance(instance);
263
264 inst->disp->layer_inst_disp.SubmitDebugUtilsMessageEXT(instance, messageSeverity, messageTypes, pCallbackData);
265}
266
267static VKAPI_ATTR void VKAPI_CALL debug_utils_DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger,
268 const VkAllocationCallbacks *pAllocator) {
269 struct loader_instance *inst = loader_get_instance(instance);
270 loader_platform_thread_lock_mutex(&loader_lock);
271
272 inst->disp->layer_inst_disp.DestroyDebugUtilsMessengerEXT(instance, messenger, pAllocator);
273
274 util_DestroyDebugUtilsMessenger(inst, messenger, pAllocator);
275
276 loader_platform_thread_unlock_mutex(&loader_lock);
277}
278
279// This is the instance chain terminator function for CreateDebugUtilsMessenger
280VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugUtilsMessengerEXT(VkInstance instance,
281 const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
282 const VkAllocationCallbacks *pAllocator,
283 VkDebugUtilsMessengerEXT *pMessenger) {
284 VkDebugUtilsMessengerEXT *icd_info = NULL;
285 const struct loader_icd_term *icd_term;
286 struct loader_instance *inst = (struct loader_instance *)instance;
287 VkResult res = VK_SUCCESS;
288 uint32_t storage_idx;
289 VkLayerDbgFunctionNode *pNewDbgFuncNode = NULL;
290
291#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
292 {
293#else
294 if (pAllocator != NULL) {
295 icd_info = ((VkDebugUtilsMessengerEXT *)pAllocator->pfnAllocation(pAllocator->pUserData,
296 inst->total_icd_count * sizeof(VkDebugUtilsMessengerEXT),
297 sizeof(void *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
298 if (icd_info) {
299 memset(icd_info, 0, inst->total_icd_count * sizeof(VkDebugUtilsMessengerEXT));
300 }
301 } else {
302#endif
303 icd_info = calloc(sizeof(VkDebugUtilsMessengerEXT), inst->total_icd_count);
304 }
305 if (!icd_info) {
306 res = VK_ERROR_OUT_OF_HOST_MEMORY;
307 goto out;
308 }
309
310 storage_idx = 0;
311 for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
312 if (!icd_term->dispatch.CreateDebugUtilsMessengerEXT) {
313 continue;
314 }
315
316 res = icd_term->dispatch.CreateDebugUtilsMessengerEXT(icd_term->instance, pCreateInfo, pAllocator, &icd_info[storage_idx]);
317
318 if (res != VK_SUCCESS) {
319 goto out;
320 }
321 storage_idx++;
322 }
323
324// Setup the debug report callback in the terminator since a layer may want
325// to grab the information itself (RenderDoc) and then return back to the
326// user callback a sub-set of the messages.
327#if (DEBUG_DISABLE_APP_ALLOCATORS == 0)
328 if (pAllocator != NULL) {
329 pNewDbgFuncNode = (VkLayerDbgFunctionNode *)pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(VkLayerDbgFunctionNode),
330 sizeof(int *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
331 } else {
332#else
333 {
334#endif
335 pNewDbgFuncNode = (VkLayerDbgFunctionNode *)loader_instance_heap_alloc(inst, sizeof(VkLayerDbgFunctionNode),
336 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
337 }
338 if (!pNewDbgFuncNode) {
339 res = VK_ERROR_OUT_OF_HOST_MEMORY;
340 goto out;
341 }
342 memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
343
344 pNewDbgFuncNode->is_messenger = true;
345 pNewDbgFuncNode->messenger.pfnUserCallback = pCreateInfo->pfnUserCallback;
346 pNewDbgFuncNode->messenger.messageSeverity = pCreateInfo->messageSeverity;
347 pNewDbgFuncNode->messenger.messageType = pCreateInfo->messageType;
348 pNewDbgFuncNode->pUserData = pCreateInfo->pUserData;
349 pNewDbgFuncNode->pNext = inst->DbgFunctionHead;
350 inst->DbgFunctionHead = pNewDbgFuncNode;
351
352 *(VkDebugUtilsMessengerEXT **)pMessenger = icd_info;
353 pNewDbgFuncNode->messenger.messenger = *pMessenger;
354
355out:
356
357 // Roll back on errors
358 if (VK_SUCCESS != res) {
359 storage_idx = 0;
360 for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
361 if (NULL == icd_term->dispatch.DestroyDebugUtilsMessengerEXT) {
362 continue;
363 }
364
365 if (icd_info && icd_info[storage_idx]) {
366 icd_term->dispatch.DestroyDebugUtilsMessengerEXT(icd_term->instance, icd_info[storage_idx], pAllocator);
367 }
368 storage_idx++;
369 }
370
371#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
372 {
373#else
374 if (pAllocator != NULL) {
375 if (NULL != pNewDbgFuncNode) {
376 pAllocator->pfnFree(pAllocator->pUserData, pNewDbgFuncNode);
377 }
378 if (NULL != icd_info) {
379 pAllocator->pfnFree(pAllocator->pUserData, icd_info);
380 }
381 } else {
382#endif
383 if (NULL != pNewDbgFuncNode) {
384 free(pNewDbgFuncNode);
385 }
386 if (NULL != icd_info) {
387 free(icd_info);
388 }
389 }
390 }
391
392 return res;
393}
394
395// This is the instance chain terminator function for DestroyDebugUtilsMessenger
396VKAPI_ATTR void VKAPI_CALL terminator_DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger,
397 const VkAllocationCallbacks *pAllocator) {
398 uint32_t storage_idx;
399 VkDebugUtilsMessengerEXT *icd_info;
400 const struct loader_icd_term *icd_term;
401
402 struct loader_instance *inst = (struct loader_instance *)instance;
403 icd_info = *(VkDebugUtilsMessengerEXT **)&messenger;
404 storage_idx = 0;
405 for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
406 if (NULL == icd_term->dispatch.DestroyDebugUtilsMessengerEXT) {
407 continue;
408 }
409
410 if (icd_info[storage_idx]) {
411 icd_term->dispatch.DestroyDebugUtilsMessengerEXT(icd_term->instance, icd_info[storage_idx], pAllocator);
412 }
413 storage_idx++;
414 }
415
416#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
417 {
418#else
419 if (pAllocator != NULL) {
420 pAllocator->pfnFree(pAllocator->pUserData, icd_info);
421 } else {
422#endif
423 free(icd_info);
424 }
425}
426
427// This is the instance chain terminator function for SubmitDebugUtilsMessageEXT
428VKAPI_ATTR void VKAPI_CALL terminator_SubmitDebugUtilsMessageEXT(VkInstance instance,
429 VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
430 VkDebugUtilsMessageTypeFlagsEXT messageTypes,
431 const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData) {
432 const struct loader_icd_term *icd_term;
433
434 struct loader_instance *inst = (struct loader_instance *)instance;
435
436 loader_platform_thread_lock_mutex(&loader_lock);
437 for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
438 if (icd_term->dispatch.SubmitDebugUtilsMessageEXT != NULL) {
439 icd_term->dispatch.SubmitDebugUtilsMessageEXT(icd_term->instance, messageSeverity, messageTypes, pCallbackData);
440 }
441 }
442
443 // Now that all ICDs have seen the message, call the necessary callbacks. Ignoring "bail" return value
444 // as there is nothing to bail from at this point.
445
446 util_SubmitDebugUtilsMessageEXT(inst, messageSeverity, messageTypes, pCallbackData);
447
448 loader_platform_thread_unlock_mutex(&loader_lock);
449}
450
451// VK_EXT_debug_report related items
452
453VkResult util_CreateDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
454 const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT callback) {
455 VkLayerDbgFunctionNode *pNewDbgFuncNode = NULL;
456
457#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
458 {
459#else
460 if (pAllocator != NULL) {
461 pNewDbgFuncNode = (VkLayerDbgFunctionNode *)pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(VkLayerDbgFunctionNode),
462 sizeof(int *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
463 } else {
464#endif
465 pNewDbgFuncNode = (VkLayerDbgFunctionNode *)loader_instance_heap_alloc(inst, sizeof(VkLayerDbgFunctionNode),
466 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
467 }
468 if (!pNewDbgFuncNode) {
469 return VK_ERROR_OUT_OF_HOST_MEMORY;
470 }
471 memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
472
473 pNewDbgFuncNode->is_messenger = false;
474 pNewDbgFuncNode->report.msgCallback = callback;
475 pNewDbgFuncNode->report.pfnMsgCallback = pCreateInfo->pfnCallback;
476 pNewDbgFuncNode->report.msgFlags = pCreateInfo->flags;
477 pNewDbgFuncNode->pUserData = pCreateInfo->pUserData;
478 pNewDbgFuncNode->pNext = inst->DbgFunctionHead;
479 inst->DbgFunctionHead = pNewDbgFuncNode;
480
481 return VK_SUCCESS;
482}
483
484static VKAPI_ATTR VkResult VKAPI_CALL
485debug_utils_CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
486 const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pCallback) {
487 struct loader_instance *inst = loader_get_instance(instance);
488 loader_platform_thread_lock_mutex(&loader_lock);
489 VkResult result = inst->disp->layer_inst_disp.CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
490 loader_platform_thread_unlock_mutex(&loader_lock);
491 return result;
492}
493
494// Utility function to handle reporting
495VkBool32 util_DebugReportMessage(const struct loader_instance *inst, VkFlags msgFlags, VkDebugReportObjectTypeEXT objectType,
496 uint64_t srcObject, size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
497 VkBool32 bail = false;
498 VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead;
499 VkDebugUtilsMessageSeverityFlagBitsEXT severity;
500 VkDebugUtilsMessageTypeFlagsEXT types;
501 VkDebugUtilsMessengerCallbackDataEXT callback_data;
502 VkDebugUtilsObjectNameInfoEXT object_name;
503
504 debug_utils_ReportFlagsToAnnotFlags(msgFlags, false, &severity, &types);
505 debug_utils_ReportObjectToAnnotObject(objectType, srcObject, &object_name);
506
507 callback_data.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT;
508 callback_data.pNext = NULL;
509 callback_data.flags = 0;
510 callback_data.pMessageIdName = pLayerPrefix;
511 callback_data.messageIdNumber = msgCode;
512 callback_data.pMessage = pMsg;
513 callback_data.cmdBufLabelCount = 0;
514 callback_data.pCmdBufLabels = NULL;
515 callback_data.queueLabelCount = 0;
516 callback_data.pQueueLabels = NULL;
517 callback_data.objectCount = 1;
518 callback_data.pObjects = &object_name;
519
520 while (pTrav) {
521 if (!pTrav->is_messenger && pTrav->report.msgFlags & msgFlags) {
522 if (pTrav->report.pfnMsgCallback(msgFlags, objectType, srcObject, location, msgCode, pLayerPrefix, pMsg,
523 pTrav->pUserData)) {
524 bail = true;
525 }
526 }
527 if (pTrav->is_messenger && (pTrav->messenger.messageSeverity & severity) && (pTrav->messenger.messageType & types)) {
528 if (pTrav->messenger.pfnUserCallback(severity, types, &callback_data, pTrav->pUserData)) {
529 bail = true;
530 }
531 }
532
533 pTrav = pTrav->pNext;
534 }
535
536 return bail;
537}
538
539void util_DestroyDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackEXT callback,
540 const VkAllocationCallbacks *pAllocator) {
541 VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead;
542 VkLayerDbgFunctionNode *pPrev = pTrav;
543
544 while (pTrav) {
545 if (!pTrav->is_messenger && pTrav->report.msgCallback == callback) {
546 pPrev->pNext = pTrav->pNext;
547 if (inst->DbgFunctionHead == pTrav) inst->DbgFunctionHead = pTrav->pNext;
548#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
549 {
550#else
551 if (pAllocator != NULL) {
552 pAllocator->pfnFree(pAllocator->pUserData, pTrav);
553 } else {
554#endif
555 loader_instance_heap_free(inst, pTrav);
556 }
557 break;
558 }
559 pPrev = pTrav;
560 pTrav = pTrav->pNext;
561 }
562}
563
564// This utility (used by vkInstanceCreateInfo(), looks at a pNext chain. It
565// counts any VkDebugReportCallbackCreateInfoEXT structs that it finds. It
566// then allocates array that can hold that many structs, as well as that many
567// VkDebugReportCallbackEXT handles. It then copies each
568// VkDebugReportCallbackCreateInfoEXT, and initializes each handle.
569VkResult util_CopyDebugReportCreateInfos(const void *pChain, const VkAllocationCallbacks *pAllocator, uint32_t *num_callbacks,
570 VkDebugReportCallbackCreateInfoEXT **infos, VkDebugReportCallbackEXT **callbacks) {
571 uint32_t n = *num_callbacks = 0;
572 VkDebugReportCallbackCreateInfoEXT *pInfos = NULL;
573 VkDebugReportCallbackEXT *pCallbacks = NULL;
574
575 const void *pNext = pChain;
576 while (pNext) {
577 // 1st, count the number VkDebugReportCallbackCreateInfoEXT:
578 if (((VkDebugReportCallbackCreateInfoEXT *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
579 n++;
580 }
581 pNext = (void *)((VkDebugReportCallbackCreateInfoEXT *)pNext)->pNext;
582 }
583 if (n == 0) {
584 return VK_SUCCESS;
585 }
586
587// 2nd, allocate memory for each VkDebugReportCallbackCreateInfoEXT:
588#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
589 {
590#else
591 if (pAllocator != NULL) {
592 pInfos = *infos = ((VkDebugReportCallbackCreateInfoEXT *)pAllocator->pfnAllocation(
593 pAllocator->pUserData, n * sizeof(VkDebugReportCallbackCreateInfoEXT), sizeof(void *),
594 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
595 } else {
596#endif
597 pInfos = *infos = ((VkDebugReportCallbackCreateInfoEXT *)malloc(n * sizeof(VkDebugReportCallbackCreateInfoEXT)));
598 }
599 if (!pInfos) {
600 return VK_ERROR_OUT_OF_HOST_MEMORY;
601 }
602// 3rd, allocate memory for a unique handle for each callback:
603#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
604 {
605#else
606 if (pAllocator != NULL) {
607 pCallbacks = *callbacks = ((VkDebugReportCallbackEXT *)pAllocator->pfnAllocation(
608 pAllocator->pUserData, n * sizeof(VkDebugReportCallbackEXT), sizeof(void *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
609 if (!pCallbacks) {
610 pAllocator->pfnFree(pAllocator->pUserData, pInfos);
611 return VK_ERROR_OUT_OF_HOST_MEMORY;
612 }
613 } else {
614#endif
615 pCallbacks = *callbacks = ((VkDebugReportCallbackEXT *)malloc(n * sizeof(VkDebugReportCallbackEXT)));
616 if (!pCallbacks) {
617 free(pInfos);
618 return VK_ERROR_OUT_OF_HOST_MEMORY;
619 }
620 }
621 // 4th, copy each VkDebugReportCallbackCreateInfoEXT for use by
622 // vkDestroyInstance, and assign a unique handle to each callback (just
623 // use the address of the copied VkDebugReportCallbackCreateInfoEXT):
624 pNext = pChain;
625 while (pNext) {
626 if (((VkInstanceCreateInfo *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
627 memcpy(pInfos, pNext, sizeof(VkDebugReportCallbackCreateInfoEXT));
628 *pCallbacks++ = (VkDebugReportCallbackEXT)(uintptr_t)pInfos++;
629 }
630 pNext = (void *)((VkInstanceCreateInfo *)pNext)->pNext;
631 }
632
633 *num_callbacks = n;
634 return VK_SUCCESS;
635}
636
637void util_FreeDebugReportCreateInfos(const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackCreateInfoEXT *infos,
638 VkDebugReportCallbackEXT *callbacks) {
639#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
640 {
641#else
642 if (pAllocator != NULL) {
643 pAllocator->pfnFree(pAllocator->pUserData, infos);
644 pAllocator->pfnFree(pAllocator->pUserData, callbacks);
645 } else {
646#endif
647 free(infos);
648 free(callbacks);
649 }
650}
651
652VkResult util_CreateDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator,
653 uint32_t num_callbacks, VkDebugReportCallbackCreateInfoEXT *infos,
654 VkDebugReportCallbackEXT *callbacks) {
655 VkResult rtn = VK_SUCCESS;
656 for (uint32_t i = 0; i < num_callbacks; i++) {
657 rtn = util_CreateDebugReportCallback(inst, &infos[i], pAllocator, callbacks[i]);
658 if (rtn != VK_SUCCESS) {
659 for (uint32_t j = 0; j < i; j++) {
660 util_DestroyDebugReportCallback(inst, callbacks[j], pAllocator);
661 }
662 return rtn;
663 }
664 }
665 return rtn;
666}
667
668void util_DestroyDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator, uint32_t num_callbacks,
669 VkDebugReportCallbackEXT *callbacks) {
670 for (uint32_t i = 0; i < num_callbacks; i++) {
671 util_DestroyDebugReportCallback(inst, callbacks[i], pAllocator);
672 }
673}
674
675static VKAPI_ATTR void VKAPI_CALL debug_utils_DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
676 const VkAllocationCallbacks *pAllocator) {
677 struct loader_instance *inst = loader_get_instance(instance);
678 loader_platform_thread_lock_mutex(&loader_lock);
679
680 inst->disp->layer_inst_disp.DestroyDebugReportCallbackEXT(instance, callback, pAllocator);
681
682 util_DestroyDebugReportCallback(inst, callback, pAllocator);
683
684 loader_platform_thread_unlock_mutex(&loader_lock);
685}
686
687static VKAPI_ATTR void VKAPI_CALL debug_utils_DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags,
688 VkDebugReportObjectTypeEXT objType, uint64_t object,
689 size_t location, int32_t msgCode, const char *pLayerPrefix,
690 const char *pMsg) {
691 struct loader_instance *inst = loader_get_instance(instance);
692
693 inst->disp->layer_inst_disp.DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
694}
695
696// This is the instance chain terminator function
697// for CreateDebugReportCallback
698VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugReportCallbackEXT(VkInstance instance,
699 const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
700 const VkAllocationCallbacks *pAllocator,
701 VkDebugReportCallbackEXT *pCallback) {
702 VkDebugReportCallbackEXT *icd_info = NULL;
703 const struct loader_icd_term *icd_term;
704 struct loader_instance *inst = (struct loader_instance *)instance;
705 VkResult res = VK_SUCCESS;
706 uint32_t storage_idx;
707 VkLayerDbgFunctionNode *pNewDbgFuncNode = NULL;
708
709#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
710 {
711#else
712 if (pAllocator != NULL) {
713 icd_info = ((VkDebugReportCallbackEXT *)pAllocator->pfnAllocation(pAllocator->pUserData,
714 inst->total_icd_count * sizeof(VkDebugReportCallbackEXT),
715 sizeof(void *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
716 if (icd_info) {
717 memset(icd_info, 0, inst->total_icd_count * sizeof(VkDebugReportCallbackEXT));
718 }
719 } else {
720#endif
721 icd_info = calloc(sizeof(VkDebugReportCallbackEXT), inst->total_icd_count);
722 }
723 if (!icd_info) {
724 res = VK_ERROR_OUT_OF_HOST_MEMORY;
725 goto out;
726 }
727
728 storage_idx = 0;
729 for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
730 if (!icd_term->dispatch.CreateDebugReportCallbackEXT) {
731 continue;
732 }
733
734 res = icd_term->dispatch.CreateDebugReportCallbackEXT(icd_term->instance, pCreateInfo, pAllocator, &icd_info[storage_idx]);
735
736 if (res != VK_SUCCESS) {
737 goto out;
738 }
739 storage_idx++;
740 }
741
742// Setup the debug report callback in the terminator since a layer may want
743// to grab the information itself (RenderDoc) and then return back to the
744// user callback a sub-set of the messages.
745#if (DEBUG_DISABLE_APP_ALLOCATORS == 0)
746 if (pAllocator != NULL) {
747 pNewDbgFuncNode = (VkLayerDbgFunctionNode *)pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(VkLayerDbgFunctionNode),
748 sizeof(int *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
749 } else {
750#else
751 {
752#endif
753 pNewDbgFuncNode = (VkLayerDbgFunctionNode *)loader_instance_heap_alloc(inst, sizeof(VkLayerDbgFunctionNode),
754 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
755 }
756 if (!pNewDbgFuncNode) {
757 res = VK_ERROR_OUT_OF_HOST_MEMORY;
758 goto out;
759 }
760 memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
761
762 pNewDbgFuncNode->is_messenger = false;
763 pNewDbgFuncNode->report.pfnMsgCallback = pCreateInfo->pfnCallback;
764 pNewDbgFuncNode->report.msgFlags = pCreateInfo->flags;
765 pNewDbgFuncNode->pUserData = pCreateInfo->pUserData;
766 pNewDbgFuncNode->pNext = inst->DbgFunctionHead;
767 inst->DbgFunctionHead = pNewDbgFuncNode;
768
769 *(VkDebugReportCallbackEXT **)pCallback = icd_info;
770 pNewDbgFuncNode->report.msgCallback = *pCallback;
771
772out:
773
774 // Roll back on errors
775 if (VK_SUCCESS != res) {
776 storage_idx = 0;
777 for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
778 if (NULL == icd_term->dispatch.DestroyDebugReportCallbackEXT) {
779 continue;
780 }
781
782 if (icd_info && icd_info[storage_idx]) {
783 icd_term->dispatch.DestroyDebugReportCallbackEXT(icd_term->instance, icd_info[storage_idx], pAllocator);
784 }
785 storage_idx++;
786 }
787
788#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
789 {
790#else
791 if (pAllocator != NULL) {
792 if (NULL != pNewDbgFuncNode) {
793 pAllocator->pfnFree(pAllocator->pUserData, pNewDbgFuncNode);
794 }
795 if (NULL != icd_info) {
796 pAllocator->pfnFree(pAllocator->pUserData, icd_info);
797 }
798 } else {
799#endif
800 if (NULL != pNewDbgFuncNode) {
801 free(pNewDbgFuncNode);
802 }
803 if (NULL != icd_info) {
804 free(icd_info);
805 }
806 }
807 }
808
809 return res;
810}
811
812// This is the instance chain terminator function for DestroyDebugReportCallback
813VKAPI_ATTR void VKAPI_CALL terminator_DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
814 const VkAllocationCallbacks *pAllocator) {
815 uint32_t storage_idx;
816 VkDebugReportCallbackEXT *icd_info;
817 const struct loader_icd_term *icd_term;
818
819 struct loader_instance *inst = (struct loader_instance *)instance;
820 icd_info = *(VkDebugReportCallbackEXT **)&callback;
821 storage_idx = 0;
822 for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
823 if (NULL == icd_term->dispatch.DestroyDebugReportCallbackEXT) {
824 continue;
825 }
826
827 if (icd_info[storage_idx]) {
828 icd_term->dispatch.DestroyDebugReportCallbackEXT(icd_term->instance, icd_info[storage_idx], pAllocator);
829 }
830 storage_idx++;
831 }
832
833#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
834 {
835#else
836 if (pAllocator != NULL) {
837 pAllocator->pfnFree(pAllocator->pUserData, icd_info);
838 } else {
839#endif
840 free(icd_info);
841 }
842}
843
844// This is the instance chain terminator function for DebugReportMessage
845VKAPI_ATTR void VKAPI_CALL terminator_DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags,
846 VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location,
847 int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
848 const struct loader_icd_term *icd_term;
849
850 struct loader_instance *inst = (struct loader_instance *)instance;
851
852 loader_platform_thread_lock_mutex(&loader_lock);
853 for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
854 if (icd_term->dispatch.DebugReportMessageEXT != NULL) {
855 icd_term->dispatch.DebugReportMessageEXT(icd_term->instance, flags, objType, object, location, msgCode, pLayerPrefix,
856 pMsg);
857 }
858 }
859
860 // Now that all ICDs have seen the message, call the necessary callbacks. Ignoring "bail" return value
861 // as there is nothing to bail from at this point.
862
863 util_DebugReportMessage(inst, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
864
865 loader_platform_thread_unlock_mutex(&loader_lock);
866}
867
868// General utilities
869
870static const VkExtensionProperties debug_utils_extension_info[] = {
871 {VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION},
872 {VK_EXT_DEBUG_UTILS_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_SPEC_VERSION},
873};
874
875void debug_utils_AddInstanceExtensions(const struct loader_instance *inst, struct loader_extension_list *ext_list) {
876 loader_add_to_ext_list(inst, ext_list, sizeof(debug_utils_extension_info) / sizeof(VkExtensionProperties),
877 debug_utils_extension_info);
878}
879
880void debug_utils_CreateInstance(struct loader_instance *ptr_instance, const VkInstanceCreateInfo *pCreateInfo) {
881 ptr_instance->enabled_known_extensions.ext_debug_report = 0;
882 ptr_instance->enabled_known_extensions.ext_debug_utils = 0;
883
884 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
885 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0) {
886 ptr_instance->enabled_known_extensions.ext_debug_report = 1;
887 } else if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_EXT_DEBUG_UTILS_EXTENSION_NAME) == 0) {
888 ptr_instance->enabled_known_extensions.ext_debug_utils = 1;
889 }
890 }
891}
892
893bool debug_utils_InstanceGpa(struct loader_instance *ptr_instance, const char *name, void **addr) {
894 bool ret_type = false;
895
896 *addr = NULL;
897
Lenny Komow1de11122018-02-22 11:54:18 -0700898 if (!strcmp("vkCreateDebugReportCallbackEXT", name)) {
899 *addr = ptr_instance->enabled_known_extensions.ext_debug_report == 1 ? (void *)debug_utils_CreateDebugReportCallbackEXT : NULL;
900 ret_type = true;
901 } else if (!strcmp("vkDestroyDebugReportCallbackEXT", name)) {
902 *addr = ptr_instance->enabled_known_extensions.ext_debug_report == 1 ? (void *)debug_utils_DestroyDebugReportCallbackEXT : NULL;
903 ret_type = true;
904 } else if (!strcmp("vkDebugReportMessageEXT", name)) {
905 *addr = ptr_instance->enabled_known_extensions.ext_debug_report == 1 ? (void *)debug_utils_DebugReportMessageEXT : NULL;
906 return true;
Mark Younge3e9b562017-11-09 10:37:04 -0700907 }
Lenny Komow1de11122018-02-22 11:54:18 -0700908 if (!strcmp("vkCreateDebugUtilsMessengerEXT", name)) {
909 *addr = ptr_instance->enabled_known_extensions.ext_debug_utils == 1 ? (void *)debug_utils_CreateDebugUtilsMessengerEXT : NULL;
910 ret_type = true;
911 } else if (!strcmp("vkDestroyDebugUtilsMessengerEXT", name)) {
912 *addr = ptr_instance->enabled_known_extensions.ext_debug_utils == 1 ? (void *)debug_utils_DestroyDebugUtilsMessengerEXT : NULL;
913 ret_type = true;
914 } else if (!strcmp("vkSubmitDebugUtilsMessageEXT", name)) {
915 *addr = ptr_instance->enabled_known_extensions.ext_debug_utils == 1 ? (void *)debug_utils_SubmitDebugUtilsMessageEXT : NULL;
916 ret_type = true;
Mark Younge3e9b562017-11-09 10:37:04 -0700917 }
918
919 return ret_type;
920}
921
922bool debug_utils_ReportFlagsToAnnotFlags(VkDebugReportFlagsEXT dr_flags, bool default_flag_is_spec,
923 VkDebugUtilsMessageSeverityFlagBitsEXT *da_severity,
924 VkDebugUtilsMessageTypeFlagsEXT *da_type) {
925 bool type_set = false;
926 if (NULL == da_severity || NULL == da_type) {
927 return false;
928 }
929 *da_type = 0;
John Zulaufa95b00f2018-04-12 13:15:47 -0600930 *da_severity = 0;
Mark Younge3e9b562017-11-09 10:37:04 -0700931
932 if ((dr_flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) != 0) {
933 *da_severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
934 *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
935 type_set = true;
936 } else if ((dr_flags & (VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT)) != 0) {
937 *da_severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
938 } else if ((dr_flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) != 0) {
939 *da_severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
940 } else if ((dr_flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) != 0) {
941 *da_severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
942 *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
943 type_set = true;
944 }
945
946 if ((dr_flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) != 0) {
947 *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
948 } else if (!type_set) {
949 if (default_flag_is_spec) {
950 *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
951 } else {
952 *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
953 }
954 }
955
956 return true;
957}
958
959bool debug_utils_AnnotFlagsToReportFlags(VkDebugUtilsMessageSeverityFlagBitsEXT da_severity,
960 VkDebugUtilsMessageTypeFlagsEXT da_type, VkDebugReportFlagsEXT *dr_flags) {
961 if (NULL == dr_flags) {
962 return false;
963 }
964
965 *dr_flags = 0;
966
967 if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) != 0) {
968 *dr_flags |= VK_DEBUG_REPORT_ERROR_BIT_EXT;
969 } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) != 0) {
970 if ((da_type & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) != 0) {
971 *dr_flags |= VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
972 } else {
973 *dr_flags |= VK_DEBUG_REPORT_WARNING_BIT_EXT;
974 }
975 } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) != 0) {
976 *dr_flags |= VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
977 } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) != 0) {
978 *dr_flags |= VK_DEBUG_REPORT_DEBUG_BIT_EXT;
979 }
980
981 return true;
982}
983
984bool debug_utils_ReportObjectToAnnotObject(VkDebugReportObjectTypeEXT dr_object_type, uint64_t object_handle,
985 VkDebugUtilsObjectNameInfoEXT *da_object_name_info) {
986 if (NULL == da_object_name_info) {
987 return false;
988 }
989 da_object_name_info->sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
990 da_object_name_info->pNext = NULL;
991 da_object_name_info->objectHandle = (uint64_t)(uintptr_t)object_handle;
992 da_object_name_info->pObjectName = NULL;
993 da_object_name_info->objectType = convertDebugReportObjectToCoreObject(dr_object_type);
994 return true;
995}
996
997bool debug_utils_AnnotObjectToDebugReportObject(const VkDebugUtilsObjectNameInfoEXT *da_object_name_info,
998 VkDebugReportObjectTypeEXT *dr_object_type, uint64_t *dr_object_handle) {
999 if (NULL == da_object_name_info || NULL == dr_object_type || NULL == dr_object_handle) {
1000 return false;
1001 }
1002 *dr_object_type = convertCoreObjectToDebugReportObject(da_object_name_info->objectType);
1003 *dr_object_handle = da_object_name_info->objectHandle;
1004 return true;
1005}