2
0

debug_utils.c 42 KB

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