11c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter/*
244aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburn * Copyright (c) 2015-2016 The Khronos Group Inc.
344aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburn * Copyright (c) 2015-2016 Valve Corporation
444aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburn * Copyright (c) 2015-2016 LunarG, Inc.
544aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburn * Copyright (C) 2015-2016 Google Inc.
61c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter *
743b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * Licensed under the Apache License, Version 2.0 (the "License");
843b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * you may not use this file except in compliance with the License.
943b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * You may obtain a copy of the License at
101c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter *
1143b53e83705f02245da6ae61e31273866a35b833Jon Ashburn *     http://www.apache.org/licenses/LICENSE-2.0
121c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter *
1343b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * Unless required by applicable law or agreed to in writing, software
1443b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * distributed under the License is distributed on an "AS IS" BASIS,
1543b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1643b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * See the License for the specific language governing permissions and
1743b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * limitations under the License.
181c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter *
1996cd795bb585711057cd90d37a2251419384c937Courtney Goeltzenleuchter * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
2044aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburn * Author: Jon Ashburn <jon@LunarG.com>
2196cd795bb585711057cd90d37a2251419384c937Courtney Goeltzenleuchter *
221c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter */
231c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter
24b620ace53373bb2803db70005dee39be9c184f06Courtney Goeltzenleuchter#define _GNU_SOURCE
25f1eb24969343c029c23d3cd173784861c68d4cf9Courtney Goeltzenleuchter#include <stdio.h>
261c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter#include <string.h>
271c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter#include <stdlib.h>
28f1eb24969343c029c23d3cd173784861c68d4cf9Courtney Goeltzenleuchter#include <inttypes.h>
296969851e9b282a032d0b60021a60bd6e50db7591Tony Barbour#ifndef WIN32
30c3c1f01dd2e5e956f16e0943224d58b13ada5ea4Courtney Goeltzenleuchter#include <signal.h>
31c3c1f01dd2e5e956f16e0943224d58b13ada5ea4Courtney Goeltzenleuchter#else
326969851e9b282a032d0b60021a60bd6e50db7591Tony Barbour#endif
336fb9a531b82cc9e3c603486f70ef9f60e617c3aaJon Ashburn#include "vk_loader_platform.h"
341c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter#include "debug_report.h"
35329ca9eb16cdbee7a7644fb08ade7b3d3bb32e23David Pinedo#include "vulkan/vk_layer.h"
361c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter
3744aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburntypedef void(VKAPI_PTR *PFN_stringCallback)(char *message);
38f1eb24969343c029c23d3cd173784861c68d4cf9Courtney Goeltzenleuchter
39c4748dc128c1449212884a15f67faeb616fd1f3bJon Ashburnstatic const VkExtensionProperties debug_report_extension_info = {
40bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski    .extensionName = VK_EXT_DEBUG_REPORT_EXTENSION_NAME, .specVersion = VK_EXT_DEBUG_REPORT_SPEC_VERSION,
411c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter};
421c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter
43bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskivoid debug_report_add_instance_extensions(const struct loader_instance *inst, struct loader_extension_list *ext_list) {
44e58f1a382f472101f92b7aca05ac28e972736a53Jon Ashburn    loader_add_to_ext_list(inst, ext_list, 1, &debug_report_extension_info);
451c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter}
461c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter
47bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskivoid debug_report_create_instance(struct loader_instance *ptr_instance, const VkInstanceCreateInfo *pCreateInfo) {
48fcdd4d0a9f4297bbbae12ccb24d3187da25165f8Mark Young    ptr_instance->enabled_known_extensions.ext_debug_report = 0;
4918061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter
50a4ae48bfd6f2e2a80e1f92e054a007cf90a4e218Jon Ashburn    for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
51bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0) {
52fcdd4d0a9f4297bbbae12ccb24d3187da25165f8Mark Young            ptr_instance->enabled_known_extensions.ext_debug_report = 1;
5318061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter            return;
5418061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter        }
5518061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    }
561c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter}
571c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter
58bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVkResult util_CreateDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
59bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                        const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT callback) {
604b0c7df3980851c6e872437860ac88a98b34c8c5Mark Young    VkLayerDbgFunctionNode *pNewDbgFuncNode = NULL;
614b0c7df3980851c6e872437860ac88a98b34c8c5Mark Young
6274d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
6374d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young    {
6474d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young#else
6515436c1ce3f69268ce3aeea520c16935f9f597e8Courtney Goeltzenleuchter    if (pAllocator != NULL) {
66bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        pNewDbgFuncNode = (VkLayerDbgFunctionNode *)pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(VkLayerDbgFunctionNode),
67bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                                              sizeof(int *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
6815436c1ce3f69268ce3aeea520c16935f9f597e8Courtney Goeltzenleuchter    } else {
6974d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young#endif
70bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        pNewDbgFuncNode = (VkLayerDbgFunctionNode *)loader_instance_heap_alloc(inst, sizeof(VkLayerDbgFunctionNode),
71bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                                               VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
7215436c1ce3f69268ce3aeea520c16935f9f597e8Courtney Goeltzenleuchter    }
734b0c7df3980851c6e872437860ac88a98b34c8c5Mark Young    if (!pNewDbgFuncNode) {
7415436c1ce3f69268ce3aeea520c16935f9f597e8Courtney Goeltzenleuchter        return VK_ERROR_OUT_OF_HOST_MEMORY;
754b0c7df3980851c6e872437860ac88a98b34c8c5Mark Young    }
764b0c7df3980851c6e872437860ac88a98b34c8c5Mark Young    memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
7715436c1ce3f69268ce3aeea520c16935f9f597e8Courtney Goeltzenleuchter
7815436c1ce3f69268ce3aeea520c16935f9f597e8Courtney Goeltzenleuchter    pNewDbgFuncNode->msgCallback = callback;
7915436c1ce3f69268ce3aeea520c16935f9f597e8Courtney Goeltzenleuchter    pNewDbgFuncNode->pfnMsgCallback = pCreateInfo->pfnCallback;
8015436c1ce3f69268ce3aeea520c16935f9f597e8Courtney Goeltzenleuchter    pNewDbgFuncNode->msgFlags = pCreateInfo->flags;
8115436c1ce3f69268ce3aeea520c16935f9f597e8Courtney Goeltzenleuchter    pNewDbgFuncNode->pUserData = pCreateInfo->pUserData;
8215436c1ce3f69268ce3aeea520c16935f9f597e8Courtney Goeltzenleuchter    pNewDbgFuncNode->pNext = inst->DbgFunctionHead;
8315436c1ce3f69268ce3aeea520c16935f9f597e8Courtney Goeltzenleuchter    inst->DbgFunctionHead = pNewDbgFuncNode;
8415436c1ce3f69268ce3aeea520c16935f9f597e8Courtney Goeltzenleuchter
8515436c1ce3f69268ce3aeea520c16935f9f597e8Courtney Goeltzenleuchter    return VK_SUCCESS;
8615436c1ce3f69268ce3aeea520c16935f9f597e8Courtney Goeltzenleuchter}
8715436c1ce3f69268ce3aeea520c16935f9f597e8Courtney Goeltzenleuchter
88bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic VKAPI_ATTR VkResult VKAPI_CALL
89bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskidebug_report_CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
90bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                          const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pCallback) {
910c5eea212afbc79a63f75ea5fab2526998a26e74Jon Ashburn    struct loader_instance *inst = loader_get_instance(instance);
92b40f2568bff91895d66848767fdaa540793b5162Jon Ashburn    loader_platform_thread_lock_mutex(&loader_lock);
93bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski    VkResult result = inst->disp->layer_inst_disp.CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
94b40f2568bff91895d66848767fdaa540793b5162Jon Ashburn    loader_platform_thread_unlock_mutex(&loader_lock);
951c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter    return result;
961c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter}
971c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter
986175e4b1345723e8c30c4dc4e29d4e22bb907cd3Courtney Goeltzenleuchter// Utility function to handle reporting
99bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVkBool32 util_DebugReportMessage(const struct loader_instance *inst, VkFlags msgFlags, VkDebugReportObjectTypeEXT objectType,
100bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                 uint64_t srcObject, size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
1016175e4b1345723e8c30c4dc4e29d4e22bb907cd3Courtney Goeltzenleuchter    VkBool32 bail = false;
1026175e4b1345723e8c30c4dc4e29d4e22bb907cd3Courtney Goeltzenleuchter    VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead;
1036175e4b1345723e8c30c4dc4e29d4e22bb907cd3Courtney Goeltzenleuchter    while (pTrav) {
1046175e4b1345723e8c30c4dc4e29d4e22bb907cd3Courtney Goeltzenleuchter        if (pTrav->msgFlags & msgFlags) {
105bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski            if (pTrav->pfnMsgCallback(msgFlags, objectType, srcObject, location, msgCode, pLayerPrefix, pMsg, pTrav->pUserData)) {
1066175e4b1345723e8c30c4dc4e29d4e22bb907cd3Courtney Goeltzenleuchter                bail = true;
1076175e4b1345723e8c30c4dc4e29d4e22bb907cd3Courtney Goeltzenleuchter            }
1086175e4b1345723e8c30c4dc4e29d4e22bb907cd3Courtney Goeltzenleuchter        }
1096175e4b1345723e8c30c4dc4e29d4e22bb907cd3Courtney Goeltzenleuchter        pTrav = pTrav->pNext;
1106175e4b1345723e8c30c4dc4e29d4e22bb907cd3Courtney Goeltzenleuchter    }
1116175e4b1345723e8c30c4dc4e29d4e22bb907cd3Courtney Goeltzenleuchter
1126175e4b1345723e8c30c4dc4e29d4e22bb907cd3Courtney Goeltzenleuchter    return bail;
1136175e4b1345723e8c30c4dc4e29d4e22bb907cd3Courtney Goeltzenleuchter}
1146175e4b1345723e8c30c4dc4e29d4e22bb907cd3Courtney Goeltzenleuchter
115bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskivoid util_DestroyDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackEXT callback,
11644aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburn                                     const VkAllocationCallbacks *pAllocator) {
1171c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter    VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead;
1181c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter    VkLayerDbgFunctionNode *pPrev = pTrav;
1191c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter
1201c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter    while (pTrav) {
121f6a6e223b7ca92b5e3c8b05331b500ab8f01116aCourtney Goeltzenleuchter        if (pTrav->msgCallback == callback) {
1221c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter            pPrev->pNext = pTrav->pNext;
123cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            if (inst->DbgFunctionHead == pTrav) inst->DbgFunctionHead = pTrav->pNext;
12474d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
12574d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young            {
12674d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young#else
12715436c1ce3f69268ce3aeea520c16935f9f597e8Courtney Goeltzenleuchter            if (pAllocator != NULL) {
12815436c1ce3f69268ce3aeea520c16935f9f597e8Courtney Goeltzenleuchter                pAllocator->pfnFree(pAllocator->pUserData, pTrav);
12915436c1ce3f69268ce3aeea520c16935f9f597e8Courtney Goeltzenleuchter            } else {
13074d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young#endif
13174d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young                loader_instance_heap_free(inst, pTrav);
13215436c1ce3f69268ce3aeea520c16935f9f597e8Courtney Goeltzenleuchter            }
1331c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter            break;
1341c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter        }
1351c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter        pPrev = pTrav;
1361c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter        pTrav = pTrav->pNext;
1371c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter    }
13815436c1ce3f69268ce3aeea520c16935f9f597e8Courtney Goeltzenleuchter}
13915436c1ce3f69268ce3aeea520c16935f9f597e8Courtney Goeltzenleuchter
14001b7832181f630089b0ead23580d38595ec8437eIan Elliott// This utility (used by vkInstanceCreateInfo(), looks at a pNext chain.  It
14101b7832181f630089b0ead23580d38595ec8437eIan Elliott// counts any VkDebugReportCallbackCreateInfoEXT structs that it finds.  It
14201b7832181f630089b0ead23580d38595ec8437eIan Elliott// then allocates array that can hold that many structs, as well as that many
14301b7832181f630089b0ead23580d38595ec8437eIan Elliott// VkDebugReportCallbackEXT handles.  It then copies each
14401b7832181f630089b0ead23580d38595ec8437eIan Elliott// VkDebugReportCallbackCreateInfoEXT, and initializes each handle.
145bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVkResult util_CopyDebugReportCreateInfos(const void *pChain, const VkAllocationCallbacks *pAllocator, uint32_t *num_callbacks,
146bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                         VkDebugReportCallbackCreateInfoEXT **infos, VkDebugReportCallbackEXT **callbacks) {
14701b7832181f630089b0ead23580d38595ec8437eIan Elliott    uint32_t n = *num_callbacks = 0;
14874d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young    VkDebugReportCallbackCreateInfoEXT *pInfos = NULL;
14974d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young    VkDebugReportCallbackEXT *pCallbacks = NULL;
15001b7832181f630089b0ead23580d38595ec8437eIan Elliott
15101b7832181f630089b0ead23580d38595ec8437eIan Elliott    // NOTE: The loader is not using pAllocator, and so this function doesn't
15201b7832181f630089b0ead23580d38595ec8437eIan Elliott    // either.
15301b7832181f630089b0ead23580d38595ec8437eIan Elliott
15401b7832181f630089b0ead23580d38595ec8437eIan Elliott    const void *pNext = pChain;
15501b7832181f630089b0ead23580d38595ec8437eIan Elliott    while (pNext) {
15601b7832181f630089b0ead23580d38595ec8437eIan Elliott        // 1st, count the number VkDebugReportCallbackCreateInfoEXT:
157bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        if (((VkDebugReportCallbackCreateInfoEXT *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
15801b7832181f630089b0ead23580d38595ec8437eIan Elliott            n++;
15901b7832181f630089b0ead23580d38595ec8437eIan Elliott        }
16001b7832181f630089b0ead23580d38595ec8437eIan Elliott        pNext = (void *)((VkDebugReportCallbackCreateInfoEXT *)pNext)->pNext;
16101b7832181f630089b0ead23580d38595ec8437eIan Elliott    }
16201b7832181f630089b0ead23580d38595ec8437eIan Elliott    if (n == 0) {
16301b7832181f630089b0ead23580d38595ec8437eIan Elliott        return VK_SUCCESS;
16401b7832181f630089b0ead23580d38595ec8437eIan Elliott    }
16501b7832181f630089b0ead23580d38595ec8437eIan Elliott
16674d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young// 2nd, allocate memory for each VkDebugReportCallbackCreateInfoEXT:
16774d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
16874d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young    {
16974d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young#else
17074d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young    if (pAllocator != NULL) {
171bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        pInfos = *infos = ((VkDebugReportCallbackCreateInfoEXT *)pAllocator->pfnAllocation(
172bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski            pAllocator->pUserData, n * sizeof(VkDebugReportCallbackCreateInfoEXT), sizeof(void *),
173bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski            VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
17474d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young    } else {
17574d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young#endif
176bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        pInfos = *infos = ((VkDebugReportCallbackCreateInfoEXT *)malloc(n * sizeof(VkDebugReportCallbackCreateInfoEXT)));
17774d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young    }
17801b7832181f630089b0ead23580d38595ec8437eIan Elliott    if (!pInfos) {
17901b7832181f630089b0ead23580d38595ec8437eIan Elliott        return VK_ERROR_OUT_OF_HOST_MEMORY;
18001b7832181f630089b0ead23580d38595ec8437eIan Elliott    }
18174d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young// 3rd, allocate memory for a unique handle for each callback:
18274d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
18374d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young    {
18474d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young#else
18574d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young    if (pAllocator != NULL) {
186bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        pCallbacks = *callbacks = ((VkDebugReportCallbackEXT *)pAllocator->pfnAllocation(
187bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski            pAllocator->pUserData, n * sizeof(VkDebugReportCallbackEXT), sizeof(void *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
188bf22357d455c4cdaf49cc502f72fcf8554ff8e74Mark Young        if (!pCallbacks) {
189bf22357d455c4cdaf49cc502f72fcf8554ff8e74Mark Young            pAllocator->pfnFree(pAllocator->pUserData, pInfos);
190bf22357d455c4cdaf49cc502f72fcf8554ff8e74Mark Young            return VK_ERROR_OUT_OF_HOST_MEMORY;
191bf22357d455c4cdaf49cc502f72fcf8554ff8e74Mark Young        }
19274d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young    } else {
19374d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young#endif
194bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        pCallbacks = *callbacks = ((VkDebugReportCallbackEXT *)malloc(n * sizeof(VkDebugReportCallbackEXT)));
195bf22357d455c4cdaf49cc502f72fcf8554ff8e74Mark Young        if (!pCallbacks) {
196bf22357d455c4cdaf49cc502f72fcf8554ff8e74Mark Young            free(pInfos);
197bf22357d455c4cdaf49cc502f72fcf8554ff8e74Mark Young            return VK_ERROR_OUT_OF_HOST_MEMORY;
198bf22357d455c4cdaf49cc502f72fcf8554ff8e74Mark Young        }
19901b7832181f630089b0ead23580d38595ec8437eIan Elliott    }
20001b7832181f630089b0ead23580d38595ec8437eIan Elliott    // 4th, copy each VkDebugReportCallbackCreateInfoEXT for use by
20101b7832181f630089b0ead23580d38595ec8437eIan Elliott    // vkDestroyInstance, and assign a unique handle to each callback (just
20201b7832181f630089b0ead23580d38595ec8437eIan Elliott    // use the address of the copied VkDebugReportCallbackCreateInfoEXT):
20301b7832181f630089b0ead23580d38595ec8437eIan Elliott    pNext = pChain;
20401b7832181f630089b0ead23580d38595ec8437eIan Elliott    while (pNext) {
205bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        if (((VkInstanceCreateInfo *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
2069b2a8c927eea827c93a84f73a15dba37b8a7ef0aJon Ashburn            memcpy(pInfos, pNext, sizeof(VkDebugReportCallbackCreateInfoEXT));
207088356fe508f2d968e1ce3328d14570be756edfeKarl Schultz            *pCallbacks++ = (VkDebugReportCallbackEXT)(uintptr_t)pInfos++;
20801b7832181f630089b0ead23580d38595ec8437eIan Elliott        }
20901b7832181f630089b0ead23580d38595ec8437eIan Elliott        pNext = (void *)((VkInstanceCreateInfo *)pNext)->pNext;
21001b7832181f630089b0ead23580d38595ec8437eIan Elliott    }
21101b7832181f630089b0ead23580d38595ec8437eIan Elliott
21201b7832181f630089b0ead23580d38595ec8437eIan Elliott    *num_callbacks = n;
21301b7832181f630089b0ead23580d38595ec8437eIan Elliott    return VK_SUCCESS;
21401b7832181f630089b0ead23580d38595ec8437eIan Elliott}
21501b7832181f630089b0ead23580d38595ec8437eIan Elliott
216bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskivoid util_FreeDebugReportCreateInfos(const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackCreateInfoEXT *infos,
2179b2a8c927eea827c93a84f73a15dba37b8a7ef0aJon Ashburn                                     VkDebugReportCallbackEXT *callbacks) {
218bf22357d455c4cdaf49cc502f72fcf8554ff8e74Mark Young#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
219bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski    {
220bf22357d455c4cdaf49cc502f72fcf8554ff8e74Mark Young#else
221bf22357d455c4cdaf49cc502f72fcf8554ff8e74Mark Young    if (pAllocator != NULL) {
222bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        pAllocator->pfnFree(pAllocator->pUserData, infos);
223bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        pAllocator->pfnFree(pAllocator->pUserData, callbacks);
224bf22357d455c4cdaf49cc502f72fcf8554ff8e74Mark Young    } else {
225bf22357d455c4cdaf49cc502f72fcf8554ff8e74Mark Young#endif
226bf22357d455c4cdaf49cc502f72fcf8554ff8e74Mark Young        free(infos);
227bf22357d455c4cdaf49cc502f72fcf8554ff8e74Mark Young        free(callbacks);
228bf22357d455c4cdaf49cc502f72fcf8554ff8e74Mark Young    }
22901b7832181f630089b0ead23580d38595ec8437eIan Elliott}
23001b7832181f630089b0ead23580d38595ec8437eIan Elliott
231bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVkResult util_CreateDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator,
232bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                         uint32_t num_callbacks, VkDebugReportCallbackCreateInfoEXT *infos,
233bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                         VkDebugReportCallbackEXT *callbacks) {
2341d5109d5e0dcc530b27e632e73e1be5e12a28dcdJamie Madill    VkResult rtn = VK_SUCCESS;
2359b2a8c927eea827c93a84f73a15dba37b8a7ef0aJon Ashburn    for (uint32_t i = 0; i < num_callbacks; i++) {
236bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        rtn = util_CreateDebugReportCallback(inst, &infos[i], pAllocator, callbacks[i]);
23701b7832181f630089b0ead23580d38595ec8437eIan Elliott        if (rtn != VK_SUCCESS) {
2389b2a8c927eea827c93a84f73a15dba37b8a7ef0aJon Ashburn            for (uint32_t j = 0; j < i; j++) {
2399b2a8c927eea827c93a84f73a15dba37b8a7ef0aJon Ashburn                util_DestroyDebugReportCallback(inst, callbacks[j], pAllocator);
24001b7832181f630089b0ead23580d38595ec8437eIan Elliott            }
24101b7832181f630089b0ead23580d38595ec8437eIan Elliott            return rtn;
24201b7832181f630089b0ead23580d38595ec8437eIan Elliott        }
24301b7832181f630089b0ead23580d38595ec8437eIan Elliott    }
24401b7832181f630089b0ead23580d38595ec8437eIan Elliott    return rtn;
24501b7832181f630089b0ead23580d38595ec8437eIan Elliott}
24601b7832181f630089b0ead23580d38595ec8437eIan Elliott
247bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskivoid util_DestroyDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator, uint32_t num_callbacks,
2489b2a8c927eea827c93a84f73a15dba37b8a7ef0aJon Ashburn                                      VkDebugReportCallbackEXT *callbacks) {
2499b2a8c927eea827c93a84f73a15dba37b8a7ef0aJon Ashburn    for (uint32_t i = 0; i < num_callbacks; i++) {
2509b2a8c927eea827c93a84f73a15dba37b8a7ef0aJon Ashburn        util_DestroyDebugReportCallback(inst, callbacks[i], pAllocator);
25101b7832181f630089b0ead23580d38595ec8437eIan Elliott    }
25201b7832181f630089b0ead23580d38595ec8437eIan Elliott}
25301b7832181f630089b0ead23580d38595ec8437eIan Elliott
254bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic VKAPI_ATTR void VKAPI_CALL debug_report_DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
255bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                                             const VkAllocationCallbacks *pAllocator) {
25615436c1ce3f69268ce3aeea520c16935f9f597e8Courtney Goeltzenleuchter    struct loader_instance *inst = loader_get_instance(instance);
25715436c1ce3f69268ce3aeea520c16935f9f597e8Courtney Goeltzenleuchter    loader_platform_thread_lock_mutex(&loader_lock);
25815436c1ce3f69268ce3aeea520c16935f9f597e8Courtney Goeltzenleuchter
259bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski    inst->disp->layer_inst_disp.DestroyDebugReportCallbackEXT(instance, callback, pAllocator);
26015436c1ce3f69268ce3aeea520c16935f9f597e8Courtney Goeltzenleuchter
26115436c1ce3f69268ce3aeea520c16935f9f597e8Courtney Goeltzenleuchter    util_DestroyDebugReportCallback(inst, callback, pAllocator);
2621c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter
263b40f2568bff91895d66848767fdaa540793b5162Jon Ashburn    loader_platform_thread_unlock_mutex(&loader_lock);
2641c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter}
2651c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter
266bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic VKAPI_ATTR void VKAPI_CALL debug_report_DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags,
267bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                                     VkDebugReportObjectTypeEXT objType, uint64_t object,
268bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                                     size_t location, int32_t msgCode, const char *pLayerPrefix,
269bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                                     const char *pMsg) {
2706175e4b1345723e8c30c4dc4e29d4e22bb907cd3Courtney Goeltzenleuchter    struct loader_instance *inst = loader_get_instance(instance);
2716175e4b1345723e8c30c4dc4e29d4e22bb907cd3Courtney Goeltzenleuchter
272bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski    inst->disp->layer_inst_disp.DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
2736175e4b1345723e8c30c4dc4e29d4e22bb907cd3Courtney Goeltzenleuchter}
2741c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter
2757b06221f2c4cb2205e0363afe1ce59b81aa144a1Mark Young// This is the instance chain terminator function
2767b06221f2c4cb2205e0363afe1ce59b81aa144a1Mark Young// for CreateDebugReportCallback
2777b06221f2c4cb2205e0363afe1ce59b81aa144a1Mark YoungVKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugReportCallbackEXT(VkInstance instance,
2787b06221f2c4cb2205e0363afe1ce59b81aa144a1Mark Young                                                                       const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
2797b06221f2c4cb2205e0363afe1ce59b81aa144a1Mark Young                                                                       const VkAllocationCallbacks *pAllocator,
2807b06221f2c4cb2205e0363afe1ce59b81aa144a1Mark Young                                                                       VkDebugReportCallbackEXT *pCallback) {
28180aa1b733b81aed156972155d262b0da46d18ab2Mark Young    VkDebugReportCallbackEXT *icd_info = NULL;
2829df25fd79d24280e2cd3e86e3d56ed135d807d70Mark Young    const struct loader_icd_term *icd_term;
28344aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburn    struct loader_instance *inst = (struct loader_instance *)instance;
284c50a5987320b2578adba60ae7071a099675977e8Karl Schultz    VkResult res = VK_SUCCESS;
2851c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter    uint32_t storage_idx;
2864b0c7df3980851c6e872437860ac88a98b34c8c5Mark Young    VkLayerDbgFunctionNode *pNewDbgFuncNode = NULL;
2871c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter
28874d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
28974d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young    {
29074d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young#else
29174d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young    if (pAllocator != NULL) {
292bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        icd_info = ((VkDebugReportCallbackEXT *)pAllocator->pfnAllocation(pAllocator->pUserData,
293bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                                          inst->total_icd_count * sizeof(VkDebugReportCallbackEXT),
294bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                                          sizeof(void *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
29598fa844b22ed570ca2688e2e64d31b041ae01346Karl Schultz        if (icd_info) {
296bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski            memset(icd_info, 0, inst->total_icd_count * sizeof(VkDebugReportCallbackEXT));
29798fa844b22ed570ca2688e2e64d31b041ae01346Karl Schultz        }
29874d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young    } else {
29974d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young#endif
300bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        icd_info = calloc(sizeof(VkDebugReportCallbackEXT), inst->total_icd_count);
30174d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young    }
3021c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter    if (!icd_info) {
30380aa1b733b81aed156972155d262b0da46d18ab2Mark Young        res = VK_ERROR_OUT_OF_HOST_MEMORY;
30480aa1b733b81aed156972155d262b0da46d18ab2Mark Young        goto out;
3051c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter    }
3061c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter
3071c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter    storage_idx = 0;
3089df25fd79d24280e2cd3e86e3d56ed135d807d70Mark Young    for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
3097b06221f2c4cb2205e0363afe1ce59b81aa144a1Mark Young        if (!icd_term->dispatch.CreateDebugReportCallbackEXT) {
3101c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter            continue;
3111c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter        }
3121c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter
3137b06221f2c4cb2205e0363afe1ce59b81aa144a1Mark Young        res = icd_term->dispatch.CreateDebugReportCallbackEXT(icd_term->instance, pCreateInfo, pAllocator, &icd_info[storage_idx]);
3141c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter
3151c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter        if (res != VK_SUCCESS) {
31680aa1b733b81aed156972155d262b0da46d18ab2Mark Young            goto out;
3171c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter        }
3181c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter        storage_idx++;
3191c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter    }
3201c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter
321bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski// Setup the debug report callback in the terminator since a layer may want
322bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski// to grab the information itself (RenderDoc) and then return back to the
323bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski// user callback a sub-set of the messages.
3244b0c7df3980851c6e872437860ac88a98b34c8c5Mark Young#if (DEBUG_DISABLE_APP_ALLOCATORS == 0)
3254b0c7df3980851c6e872437860ac88a98b34c8c5Mark Young    if (pAllocator != NULL) {
326bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        pNewDbgFuncNode = (VkLayerDbgFunctionNode *)pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(VkLayerDbgFunctionNode),
327bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                                              sizeof(int *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
3284b0c7df3980851c6e872437860ac88a98b34c8c5Mark Young    } else {
3294b0c7df3980851c6e872437860ac88a98b34c8c5Mark Young#else
3304b0c7df3980851c6e872437860ac88a98b34c8c5Mark Young    {
3314b0c7df3980851c6e872437860ac88a98b34c8c5Mark Young#endif
332bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        pNewDbgFuncNode = (VkLayerDbgFunctionNode *)loader_instance_heap_alloc(inst, sizeof(VkLayerDbgFunctionNode),
333bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                                               VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
3344b0c7df3980851c6e872437860ac88a98b34c8c5Mark Young    }
3354b0c7df3980851c6e872437860ac88a98b34c8c5Mark Young    if (!pNewDbgFuncNode) {
33680aa1b733b81aed156972155d262b0da46d18ab2Mark Young        res = VK_ERROR_OUT_OF_HOST_MEMORY;
33780aa1b733b81aed156972155d262b0da46d18ab2Mark Young        goto out;
3384b0c7df3980851c6e872437860ac88a98b34c8c5Mark Young    }
3394b0c7df3980851c6e872437860ac88a98b34c8c5Mark Young    memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
3404b0c7df3980851c6e872437860ac88a98b34c8c5Mark Young
3414b0c7df3980851c6e872437860ac88a98b34c8c5Mark Young    pNewDbgFuncNode->pfnMsgCallback = pCreateInfo->pfnCallback;
3424b0c7df3980851c6e872437860ac88a98b34c8c5Mark Young    pNewDbgFuncNode->msgFlags = pCreateInfo->flags;
3434b0c7df3980851c6e872437860ac88a98b34c8c5Mark Young    pNewDbgFuncNode->pUserData = pCreateInfo->pUserData;
3444b0c7df3980851c6e872437860ac88a98b34c8c5Mark Young    pNewDbgFuncNode->pNext = inst->DbgFunctionHead;
3454b0c7df3980851c6e872437860ac88a98b34c8c5Mark Young    inst->DbgFunctionHead = pNewDbgFuncNode;
3464b0c7df3980851c6e872437860ac88a98b34c8c5Mark Young
34780aa1b733b81aed156972155d262b0da46d18ab2Mark Young    *(VkDebugReportCallbackEXT **)pCallback = icd_info;
34880aa1b733b81aed156972155d262b0da46d18ab2Mark Young    pNewDbgFuncNode->msgCallback = *pCallback;
34980aa1b733b81aed156972155d262b0da46d18ab2Mark Young
35080aa1b733b81aed156972155d262b0da46d18ab2Mark Youngout:
35180aa1b733b81aed156972155d262b0da46d18ab2Mark Young
35280aa1b733b81aed156972155d262b0da46d18ab2Mark Young    // Roll back on errors
353009ff5c43173a4551b2411ba90433d92944ee0deMark Young    if (VK_SUCCESS != res) {
3541c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter        storage_idx = 0;
3559df25fd79d24280e2cd3e86e3d56ed135d807d70Mark Young        for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
3567b06221f2c4cb2205e0363afe1ce59b81aa144a1Mark Young            if (NULL == icd_term->dispatch.DestroyDebugReportCallbackEXT) {
357999878744bdf08a860b9ee96ede44687eac636abMark Young                continue;
358999878744bdf08a860b9ee96ede44687eac636abMark Young            }
359999878744bdf08a860b9ee96ede44687eac636abMark Young
36098fa844b22ed570ca2688e2e64d31b041ae01346Karl Schultz            if (icd_info && icd_info[storage_idx]) {
3617b06221f2c4cb2205e0363afe1ce59b81aa144a1Mark Young                icd_term->dispatch.DestroyDebugReportCallbackEXT(icd_term->instance, icd_info[storage_idx], pAllocator);
3621c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter            }
3631c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter            storage_idx++;
3641c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter        }
3651c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter
36680aa1b733b81aed156972155d262b0da46d18ab2Mark Young#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
36780aa1b733b81aed156972155d262b0da46d18ab2Mark Young        {
36880aa1b733b81aed156972155d262b0da46d18ab2Mark Young#else
36980aa1b733b81aed156972155d262b0da46d18ab2Mark Young        if (pAllocator != NULL) {
37080aa1b733b81aed156972155d262b0da46d18ab2Mark Young            if (NULL != pNewDbgFuncNode) {
37180aa1b733b81aed156972155d262b0da46d18ab2Mark Young                pAllocator->pfnFree(pAllocator->pUserData, pNewDbgFuncNode);
37280aa1b733b81aed156972155d262b0da46d18ab2Mark Young            }
37380aa1b733b81aed156972155d262b0da46d18ab2Mark Young            if (NULL != icd_info) {
37480aa1b733b81aed156972155d262b0da46d18ab2Mark Young                pAllocator->pfnFree(pAllocator->pUserData, icd_info);
37580aa1b733b81aed156972155d262b0da46d18ab2Mark Young            }
37680aa1b733b81aed156972155d262b0da46d18ab2Mark Young        } else {
37780aa1b733b81aed156972155d262b0da46d18ab2Mark Young#endif
37880aa1b733b81aed156972155d262b0da46d18ab2Mark Young            if (NULL != pNewDbgFuncNode) {
37980aa1b733b81aed156972155d262b0da46d18ab2Mark Young                free(pNewDbgFuncNode);
38080aa1b733b81aed156972155d262b0da46d18ab2Mark Young            }
38180aa1b733b81aed156972155d262b0da46d18ab2Mark Young            if (NULL != icd_info) {
38280aa1b733b81aed156972155d262b0da46d18ab2Mark Young                free(icd_info);
38380aa1b733b81aed156972155d262b0da46d18ab2Mark Young            }
38480aa1b733b81aed156972155d262b0da46d18ab2Mark Young        }
3851c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter    }
3861c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter
387009ff5c43173a4551b2411ba90433d92944ee0deMark Young    return res;
3881c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter}
3891c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter
3907b06221f2c4cb2205e0363afe1ce59b81aa144a1Mark Young// This is the instance chain terminator function for DestroyDebugReportCallback
3917b06221f2c4cb2205e0363afe1ce59b81aa144a1Mark YoungVKAPI_ATTR void VKAPI_CALL terminator_DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
3927b06221f2c4cb2205e0363afe1ce59b81aa144a1Mark Young                                                                    const VkAllocationCallbacks *pAllocator) {
3931c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter    uint32_t storage_idx;
394acb1359c8e1528e5d67bb0101c94c48a07785098Courtney Goeltzenleuchter    VkDebugReportCallbackEXT *icd_info;
3959df25fd79d24280e2cd3e86e3d56ed135d807d70Mark Young    const struct loader_icd_term *icd_term;
3961c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter
39744aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburn    struct loader_instance *inst = (struct loader_instance *)instance;
39844aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburn    icd_info = *(VkDebugReportCallbackEXT **)&callback;
3991c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter    storage_idx = 0;
4009df25fd79d24280e2cd3e86e3d56ed135d807d70Mark Young    for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
4017b06221f2c4cb2205e0363afe1ce59b81aa144a1Mark Young        if (NULL == icd_term->dispatch.DestroyDebugReportCallbackEXT) {
402999878744bdf08a860b9ee96ede44687eac636abMark Young            continue;
403999878744bdf08a860b9ee96ede44687eac636abMark Young        }
404999878744bdf08a860b9ee96ede44687eac636abMark Young
405e420a33ff7bdcf67b8a487592af78a3ca2f29ee6Chia-I Wu        if (icd_info[storage_idx]) {
4067b06221f2c4cb2205e0363afe1ce59b81aa144a1Mark Young            icd_term->dispatch.DestroyDebugReportCallbackEXT(icd_term->instance, icd_info[storage_idx], pAllocator);
4071c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter        }
4081c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter        storage_idx++;
4091c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter    }
410bf22357d455c4cdaf49cc502f72fcf8554ff8e74Mark Young
411bf22357d455c4cdaf49cc502f72fcf8554ff8e74Mark Young#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
412bf22357d455c4cdaf49cc502f72fcf8554ff8e74Mark Young    {
413bf22357d455c4cdaf49cc502f72fcf8554ff8e74Mark Young#else
414bf22357d455c4cdaf49cc502f72fcf8554ff8e74Mark Young    if (pAllocator != NULL) {
415bf22357d455c4cdaf49cc502f72fcf8554ff8e74Mark Young        pAllocator->pfnFree(pAllocator->pUserData, icd_info);
416bf22357d455c4cdaf49cc502f72fcf8554ff8e74Mark Young    } else {
417bf22357d455c4cdaf49cc502f72fcf8554ff8e74Mark Young#endif
418bf22357d455c4cdaf49cc502f72fcf8554ff8e74Mark Young        free(icd_info);
419bf22357d455c4cdaf49cc502f72fcf8554ff8e74Mark Young    }
4201c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter}
4211c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter
4227b06221f2c4cb2205e0363afe1ce59b81aa144a1Mark Young// This is the instance chain terminator function for DebugReportMessage
4237b06221f2c4cb2205e0363afe1ce59b81aa144a1Mark YoungVKAPI_ATTR void VKAPI_CALL terminator_DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags,
4247b06221f2c4cb2205e0363afe1ce59b81aa144a1Mark Young                                                            VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location,
4257b06221f2c4cb2205e0363afe1ce59b81aa144a1Mark Young                                                            int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
4269df25fd79d24280e2cd3e86e3d56ed135d807d70Mark Young    const struct loader_icd_term *icd_term;
42715436c1ce3f69268ce3aeea520c16935f9f597e8Courtney Goeltzenleuchter
42844aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburn    struct loader_instance *inst = (struct loader_instance *)instance;
4296175e4b1345723e8c30c4dc4e29d4e22bb907cd3Courtney Goeltzenleuchter
43015436c1ce3f69268ce3aeea520c16935f9f597e8Courtney Goeltzenleuchter    loader_platform_thread_lock_mutex(&loader_lock);
4319df25fd79d24280e2cd3e86e3d56ed135d807d70Mark Young    for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
4327b06221f2c4cb2205e0363afe1ce59b81aa144a1Mark Young        if (icd_term->dispatch.DebugReportMessageEXT != NULL) {
4337b06221f2c4cb2205e0363afe1ce59b81aa144a1Mark Young            icd_term->dispatch.DebugReportMessageEXT(icd_term->instance, flags, objType, object, location, msgCode, pLayerPrefix,
4347b06221f2c4cb2205e0363afe1ce59b81aa144a1Mark Young                                                     pMsg);
4356175e4b1345723e8c30c4dc4e29d4e22bb907cd3Courtney Goeltzenleuchter        }
4366175e4b1345723e8c30c4dc4e29d4e22bb907cd3Courtney Goeltzenleuchter    }
4376175e4b1345723e8c30c4dc4e29d4e22bb907cd3Courtney Goeltzenleuchter
4387b06221f2c4cb2205e0363afe1ce59b81aa144a1Mark Young    // Now that all ICDs have seen the message, call the necessary callbacks.  Ignoring "bail" return value
4397b06221f2c4cb2205e0363afe1ce59b81aa144a1Mark Young    // as there is nothing to bail from at this point.
44015436c1ce3f69268ce3aeea520c16935f9f597e8Courtney Goeltzenleuchter
441bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski    util_DebugReportMessage(inst, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
44215436c1ce3f69268ce3aeea520c16935f9f597e8Courtney Goeltzenleuchter
44315436c1ce3f69268ce3aeea520c16935f9f597e8Courtney Goeltzenleuchter    loader_platform_thread_unlock_mutex(&loader_lock);
4446175e4b1345723e8c30c4dc4e29d4e22bb907cd3Courtney Goeltzenleuchter}
4456175e4b1345723e8c30c4dc4e29d4e22bb907cd3Courtney Goeltzenleuchter
446bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskibool debug_report_instance_gpa(struct loader_instance *ptr_instance, const char *name, void **addr) {
447994560074f43babedf590909b2af41aca59167baJon Ashburn    // debug_report is currently advertised to be supported by the loader,
448994560074f43babedf590909b2af41aca59167baJon Ashburn    // so always return the entry points if name matches and it's enabled
44905b4ec611004b014bc39851c5ef6ebf300a2f8cbJon Ashburn    *addr = NULL;
45005b4ec611004b014bc39851c5ef6ebf300a2f8cbJon Ashburn
451acb1359c8e1528e5d67bb0101c94c48a07785098Courtney Goeltzenleuchter    if (!strcmp("vkCreateDebugReportCallbackEXT", name)) {
452bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        *addr = (ptr_instance->enabled_known_extensions.ext_debug_report == 1) ? (void *)debug_report_CreateDebugReportCallbackEXT
453bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                                               : NULL;
45405b4ec611004b014bc39851c5ef6ebf300a2f8cbJon Ashburn        return true;
45505b4ec611004b014bc39851c5ef6ebf300a2f8cbJon Ashburn    }
456acb1359c8e1528e5d67bb0101c94c48a07785098Courtney Goeltzenleuchter    if (!strcmp("vkDestroyDebugReportCallbackEXT", name)) {
457bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        *addr = (ptr_instance->enabled_known_extensions.ext_debug_report == 1) ? (void *)debug_report_DestroyDebugReportCallbackEXT
458bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                                               : NULL;
45905b4ec611004b014bc39851c5ef6ebf300a2f8cbJon Ashburn        return true;
46005b4ec611004b014bc39851c5ef6ebf300a2f8cbJon Ashburn    }
461acb1359c8e1528e5d67bb0101c94c48a07785098Courtney Goeltzenleuchter    if (!strcmp("vkDebugReportMessageEXT", name)) {
462bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        *addr = (ptr_instance->enabled_known_extensions.ext_debug_report == 1) ? (void *)debug_report_DebugReportMessageEXT : NULL;
4636175e4b1345723e8c30c4dc4e29d4e22bb907cd3Courtney Goeltzenleuchter        return true;
4646175e4b1345723e8c30c4dc4e29d4e22bb907cd3Courtney Goeltzenleuchter    }
46505b4ec611004b014bc39851c5ef6ebf300a2f8cbJon Ashburn    return false;
4661c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter}
467