Implement initial VK_EXT_debug_utils changes
authorMark Young <marky@lunarg.com>
Thu, 9 Nov 2017 17:37:04 +0000 (10:37 -0700)
committerMike Schuchardt <mikes@lunarg.com>
Fri, 9 Mar 2018 20:54:31 +0000 (13:54 -0700)
This affects the loader, scripts, and layers and introduces the
changes to support the VK_EXT_debug_utils extension.

Change-Id: Ia5336f63e85b00f1e59416c06aacd4ae331fd692

18 files changed:
loader/CMakeLists.txt
loader/debug_report.c [deleted file]
loader/debug_report.h [deleted file]
loader/debug_utils.c [new file with mode: 0644]
loader/debug_utils.h [new file with mode: 0644]
loader/extension_manual.c
loader/gpa_helper.h
loader/loader.c
loader/loader.h
loader/trampoline.c
loader/vk_loader_layer.h
scripts/helper_file_generator.py
scripts/loader_extension_generator.py
scripts/object_tracker_generator.py
scripts/parameter_validation_generator.py
scripts/threading_generator.py
scripts/unique_objects_generator.py
scripts/vuid_mapping.py

index 2f96665afaeaae30e4f86436ecf6928edb1816e9..f543f8617ab51ce747a6a891028c97de3b7bf5f4 100644 (file)
@@ -75,8 +75,8 @@ set(NORMAL_LOADER_SRCS
     trampoline.c
     wsi.c
     wsi.h
-    debug_report.c
-    debug_report.h
+    debug_utils.c
+    debug_utils.h
     gpa_helper.h
     cJSON.c
     cJSON.h
diff --git a/loader/debug_report.c b/loader/debug_report.c
deleted file mode 100644 (file)
index 04e55cc..0000000
+++ /dev/null
@@ -1,466 +0,0 @@
-/*
- * Copyright (c) 2015-2016 The Khronos Group Inc.
- * Copyright (c) 2015-2016 Valve Corporation
- * Copyright (c) 2015-2016 LunarG, Inc.
- * Copyright (C) 2015-2016 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
- * Author: Jon Ashburn <jon@LunarG.com>
- *
- */
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <inttypes.h>
-#ifndef WIN32
-#include <signal.h>
-#else
-#endif
-#include "vk_loader_platform.h"
-#include "debug_report.h"
-#include "vulkan/vk_layer.h"
-
-typedef void(VKAPI_PTR *PFN_stringCallback)(char *message);
-
-static const VkExtensionProperties debug_report_extension_info = {
-    .extensionName = VK_EXT_DEBUG_REPORT_EXTENSION_NAME, .specVersion = VK_EXT_DEBUG_REPORT_SPEC_VERSION,
-};
-
-void debug_report_add_instance_extensions(const struct loader_instance *inst, struct loader_extension_list *ext_list) {
-    loader_add_to_ext_list(inst, ext_list, 1, &debug_report_extension_info);
-}
-
-void debug_report_create_instance(struct loader_instance *ptr_instance, const VkInstanceCreateInfo *pCreateInfo) {
-    ptr_instance->enabled_known_extensions.ext_debug_report = 0;
-
-    for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
-        if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0) {
-            ptr_instance->enabled_known_extensions.ext_debug_report = 1;
-            return;
-        }
-    }
-}
-
-VkResult util_CreateDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
-                                        const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT callback) {
-    VkLayerDbgFunctionNode *pNewDbgFuncNode = NULL;
-
-#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
-    {
-#else
-    if (pAllocator != NULL) {
-        pNewDbgFuncNode = (VkLayerDbgFunctionNode *)pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(VkLayerDbgFunctionNode),
-                                                                              sizeof(int *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
-    } else {
-#endif
-        pNewDbgFuncNode = (VkLayerDbgFunctionNode *)loader_instance_heap_alloc(inst, sizeof(VkLayerDbgFunctionNode),
-                                                                               VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
-    }
-    if (!pNewDbgFuncNode) {
-        return VK_ERROR_OUT_OF_HOST_MEMORY;
-    }
-    memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
-
-    pNewDbgFuncNode->msgCallback = callback;
-    pNewDbgFuncNode->pfnMsgCallback = pCreateInfo->pfnCallback;
-    pNewDbgFuncNode->msgFlags = pCreateInfo->flags;
-    pNewDbgFuncNode->pUserData = pCreateInfo->pUserData;
-    pNewDbgFuncNode->pNext = inst->DbgFunctionHead;
-    inst->DbgFunctionHead = pNewDbgFuncNode;
-
-    return VK_SUCCESS;
-}
-
-static VKAPI_ATTR VkResult VKAPI_CALL
-debug_report_CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
-                                          const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pCallback) {
-    struct loader_instance *inst = loader_get_instance(instance);
-    loader_platform_thread_lock_mutex(&loader_lock);
-    VkResult result = inst->disp->layer_inst_disp.CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
-    loader_platform_thread_unlock_mutex(&loader_lock);
-    return result;
-}
-
-// Utility function to handle reporting
-VkBool32 util_DebugReportMessage(const struct loader_instance *inst, VkFlags msgFlags, VkDebugReportObjectTypeEXT objectType,
-                                 uint64_t srcObject, size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
-    VkBool32 bail = false;
-    VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead;
-    while (pTrav) {
-        if (pTrav->msgFlags & msgFlags) {
-            if (pTrav->pfnMsgCallback(msgFlags, objectType, srcObject, location, msgCode, pLayerPrefix, pMsg, pTrav->pUserData)) {
-                bail = true;
-            }
-        }
-        pTrav = pTrav->pNext;
-    }
-
-    return bail;
-}
-
-void util_DestroyDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackEXT callback,
-                                     const VkAllocationCallbacks *pAllocator) {
-    VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead;
-    VkLayerDbgFunctionNode *pPrev = pTrav;
-
-    while (pTrav) {
-        if (pTrav->msgCallback == callback) {
-            pPrev->pNext = pTrav->pNext;
-            if (inst->DbgFunctionHead == pTrav) inst->DbgFunctionHead = pTrav->pNext;
-#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
-            {
-#else
-            if (pAllocator != NULL) {
-                pAllocator->pfnFree(pAllocator->pUserData, pTrav);
-            } else {
-#endif
-                loader_instance_heap_free(inst, pTrav);
-            }
-            break;
-        }
-        pPrev = pTrav;
-        pTrav = pTrav->pNext;
-    }
-}
-
-// This utility (used by vkInstanceCreateInfo(), looks at a pNext chain.  It
-// counts any VkDebugReportCallbackCreateInfoEXT structs that it finds.  It
-// then allocates array that can hold that many structs, as well as that many
-// VkDebugReportCallbackEXT handles.  It then copies each
-// VkDebugReportCallbackCreateInfoEXT, and initializes each handle.
-VkResult util_CopyDebugReportCreateInfos(const void *pChain, const VkAllocationCallbacks *pAllocator, uint32_t *num_callbacks,
-                                         VkDebugReportCallbackCreateInfoEXT **infos, VkDebugReportCallbackEXT **callbacks) {
-    uint32_t n = *num_callbacks = 0;
-    VkDebugReportCallbackCreateInfoEXT *pInfos = NULL;
-    VkDebugReportCallbackEXT *pCallbacks = NULL;
-
-    // NOTE: The loader is not using pAllocator, and so this function doesn't
-    // either.
-
-    const void *pNext = pChain;
-    while (pNext) {
-        // 1st, count the number VkDebugReportCallbackCreateInfoEXT:
-        if (((VkDebugReportCallbackCreateInfoEXT *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
-            n++;
-        }
-        pNext = (void *)((VkDebugReportCallbackCreateInfoEXT *)pNext)->pNext;
-    }
-    if (n == 0) {
-        return VK_SUCCESS;
-    }
-
-// 2nd, allocate memory for each VkDebugReportCallbackCreateInfoEXT:
-#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
-    {
-#else
-    if (pAllocator != NULL) {
-        pInfos = *infos = ((VkDebugReportCallbackCreateInfoEXT *)pAllocator->pfnAllocation(
-            pAllocator->pUserData, n * sizeof(VkDebugReportCallbackCreateInfoEXT), sizeof(void *),
-            VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
-    } else {
-#endif
-        pInfos = *infos = ((VkDebugReportCallbackCreateInfoEXT *)malloc(n * sizeof(VkDebugReportCallbackCreateInfoEXT)));
-    }
-    if (!pInfos) {
-        return VK_ERROR_OUT_OF_HOST_MEMORY;
-    }
-// 3rd, allocate memory for a unique handle for each callback:
-#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
-    {
-#else
-    if (pAllocator != NULL) {
-        pCallbacks = *callbacks = ((VkDebugReportCallbackEXT *)pAllocator->pfnAllocation(
-            pAllocator->pUserData, n * sizeof(VkDebugReportCallbackEXT), sizeof(void *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
-        if (!pCallbacks) {
-            pAllocator->pfnFree(pAllocator->pUserData, pInfos);
-            return VK_ERROR_OUT_OF_HOST_MEMORY;
-        }
-    } else {
-#endif
-        pCallbacks = *callbacks = ((VkDebugReportCallbackEXT *)malloc(n * sizeof(VkDebugReportCallbackEXT)));
-        if (!pCallbacks) {
-            free(pInfos);
-            return VK_ERROR_OUT_OF_HOST_MEMORY;
-        }
-    }
-    // 4th, copy each VkDebugReportCallbackCreateInfoEXT for use by
-    // vkDestroyInstance, and assign a unique handle to each callback (just
-    // use the address of the copied VkDebugReportCallbackCreateInfoEXT):
-    pNext = pChain;
-    while (pNext) {
-        if (((VkInstanceCreateInfo *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
-            memcpy(pInfos, pNext, sizeof(VkDebugReportCallbackCreateInfoEXT));
-            *pCallbacks++ = (VkDebugReportCallbackEXT)(uintptr_t)pInfos++;
-        }
-        pNext = (void *)((VkInstanceCreateInfo *)pNext)->pNext;
-    }
-
-    *num_callbacks = n;
-    return VK_SUCCESS;
-}
-
-void util_FreeDebugReportCreateInfos(const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackCreateInfoEXT *infos,
-                                     VkDebugReportCallbackEXT *callbacks) {
-#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
-    {
-#else
-    if (pAllocator != NULL) {
-        pAllocator->pfnFree(pAllocator->pUserData, infos);
-        pAllocator->pfnFree(pAllocator->pUserData, callbacks);
-    } else {
-#endif
-        free(infos);
-        free(callbacks);
-    }
-}
-
-VkResult util_CreateDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator,
-                                         uint32_t num_callbacks, VkDebugReportCallbackCreateInfoEXT *infos,
-                                         VkDebugReportCallbackEXT *callbacks) {
-    VkResult rtn = VK_SUCCESS;
-    for (uint32_t i = 0; i < num_callbacks; i++) {
-        rtn = util_CreateDebugReportCallback(inst, &infos[i], pAllocator, callbacks[i]);
-        if (rtn != VK_SUCCESS) {
-            for (uint32_t j = 0; j < i; j++) {
-                util_DestroyDebugReportCallback(inst, callbacks[j], pAllocator);
-            }
-            return rtn;
-        }
-    }
-    return rtn;
-}
-
-void util_DestroyDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator, uint32_t num_callbacks,
-                                      VkDebugReportCallbackEXT *callbacks) {
-    for (uint32_t i = 0; i < num_callbacks; i++) {
-        util_DestroyDebugReportCallback(inst, callbacks[i], pAllocator);
-    }
-}
-
-static VKAPI_ATTR void VKAPI_CALL debug_report_DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
-                                                                             const VkAllocationCallbacks *pAllocator) {
-    struct loader_instance *inst = loader_get_instance(instance);
-    loader_platform_thread_lock_mutex(&loader_lock);
-
-    inst->disp->layer_inst_disp.DestroyDebugReportCallbackEXT(instance, callback, pAllocator);
-
-    util_DestroyDebugReportCallback(inst, callback, pAllocator);
-
-    loader_platform_thread_unlock_mutex(&loader_lock);
-}
-
-static VKAPI_ATTR void VKAPI_CALL debug_report_DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags,
-                                                                     VkDebugReportObjectTypeEXT objType, uint64_t object,
-                                                                     size_t location, int32_t msgCode, const char *pLayerPrefix,
-                                                                     const char *pMsg) {
-    struct loader_instance *inst = loader_get_instance(instance);
-
-    inst->disp->layer_inst_disp.DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
-}
-
-// This is the instance chain terminator function
-// for CreateDebugReportCallback
-VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugReportCallbackEXT(VkInstance instance,
-                                                                       const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
-                                                                       const VkAllocationCallbacks *pAllocator,
-                                                                       VkDebugReportCallbackEXT *pCallback) {
-    VkDebugReportCallbackEXT *icd_info = NULL;
-    const struct loader_icd_term *icd_term;
-    struct loader_instance *inst = (struct loader_instance *)instance;
-    VkResult res = VK_SUCCESS;
-    uint32_t storage_idx;
-    VkLayerDbgFunctionNode *pNewDbgFuncNode = NULL;
-
-#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
-    {
-#else
-    if (pAllocator != NULL) {
-        icd_info = ((VkDebugReportCallbackEXT *)pAllocator->pfnAllocation(pAllocator->pUserData,
-                                                                          inst->total_icd_count * sizeof(VkDebugReportCallbackEXT),
-                                                                          sizeof(void *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
-        if (icd_info) {
-            memset(icd_info, 0, inst->total_icd_count * sizeof(VkDebugReportCallbackEXT));
-        }
-    } else {
-#endif
-        icd_info = calloc(sizeof(VkDebugReportCallbackEXT), inst->total_icd_count);
-    }
-    if (!icd_info) {
-        res = VK_ERROR_OUT_OF_HOST_MEMORY;
-        goto out;
-    }
-
-    storage_idx = 0;
-    for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
-        if (!icd_term->dispatch.CreateDebugReportCallbackEXT) {
-            continue;
-        }
-
-        res = icd_term->dispatch.CreateDebugReportCallbackEXT(icd_term->instance, pCreateInfo, pAllocator, &icd_info[storage_idx]);
-
-        if (res != VK_SUCCESS) {
-            goto out;
-        }
-        storage_idx++;
-    }
-
-// Setup the debug report callback in the terminator since a layer may want
-// to grab the information itself (RenderDoc) and then return back to the
-// user callback a sub-set of the messages.
-#if (DEBUG_DISABLE_APP_ALLOCATORS == 0)
-    if (pAllocator != NULL) {
-        pNewDbgFuncNode = (VkLayerDbgFunctionNode *)pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(VkLayerDbgFunctionNode),
-                                                                              sizeof(int *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
-    } else {
-#else
-    {
-#endif
-        pNewDbgFuncNode = (VkLayerDbgFunctionNode *)loader_instance_heap_alloc(inst, sizeof(VkLayerDbgFunctionNode),
-                                                                               VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
-    }
-    if (!pNewDbgFuncNode) {
-        res = VK_ERROR_OUT_OF_HOST_MEMORY;
-        goto out;
-    }
-    memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
-
-    pNewDbgFuncNode->pfnMsgCallback = pCreateInfo->pfnCallback;
-    pNewDbgFuncNode->msgFlags = pCreateInfo->flags;
-    pNewDbgFuncNode->pUserData = pCreateInfo->pUserData;
-    pNewDbgFuncNode->pNext = inst->DbgFunctionHead;
-    inst->DbgFunctionHead = pNewDbgFuncNode;
-
-    *(VkDebugReportCallbackEXT **)pCallback = icd_info;
-    pNewDbgFuncNode->msgCallback = *pCallback;
-
-out:
-
-    // Roll back on errors
-    if (VK_SUCCESS != res) {
-        storage_idx = 0;
-        for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
-            if (NULL == icd_term->dispatch.DestroyDebugReportCallbackEXT) {
-                continue;
-            }
-
-            if (icd_info && icd_info[storage_idx]) {
-                icd_term->dispatch.DestroyDebugReportCallbackEXT(icd_term->instance, icd_info[storage_idx], pAllocator);
-            }
-            storage_idx++;
-        }
-
-#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
-        {
-#else
-        if (pAllocator != NULL) {
-            if (NULL != pNewDbgFuncNode) {
-                pAllocator->pfnFree(pAllocator->pUserData, pNewDbgFuncNode);
-            }
-            if (NULL != icd_info) {
-                pAllocator->pfnFree(pAllocator->pUserData, icd_info);
-            }
-        } else {
-#endif
-            if (NULL != pNewDbgFuncNode) {
-                free(pNewDbgFuncNode);
-            }
-            if (NULL != icd_info) {
-                free(icd_info);
-            }
-        }
-    }
-
-    return res;
-}
-
-// This is the instance chain terminator function for DestroyDebugReportCallback
-VKAPI_ATTR void VKAPI_CALL terminator_DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
-                                                                    const VkAllocationCallbacks *pAllocator) {
-    uint32_t storage_idx;
-    VkDebugReportCallbackEXT *icd_info;
-    const struct loader_icd_term *icd_term;
-
-    struct loader_instance *inst = (struct loader_instance *)instance;
-    icd_info = *(VkDebugReportCallbackEXT **)&callback;
-    storage_idx = 0;
-    for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
-        if (NULL == icd_term->dispatch.DestroyDebugReportCallbackEXT) {
-            continue;
-        }
-
-        if (icd_info[storage_idx]) {
-            icd_term->dispatch.DestroyDebugReportCallbackEXT(icd_term->instance, icd_info[storage_idx], pAllocator);
-        }
-        storage_idx++;
-    }
-
-#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
-    {
-#else
-    if (pAllocator != NULL) {
-        pAllocator->pfnFree(pAllocator->pUserData, icd_info);
-    } else {
-#endif
-        free(icd_info);
-    }
-}
-
-// This is the instance chain terminator function for DebugReportMessage
-VKAPI_ATTR void VKAPI_CALL terminator_DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags,
-                                                            VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location,
-                                                            int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
-    const struct loader_icd_term *icd_term;
-
-    struct loader_instance *inst = (struct loader_instance *)instance;
-
-    loader_platform_thread_lock_mutex(&loader_lock);
-    for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
-        if (icd_term->dispatch.DebugReportMessageEXT != NULL) {
-            icd_term->dispatch.DebugReportMessageEXT(icd_term->instance, flags, objType, object, location, msgCode, pLayerPrefix,
-                                                     pMsg);
-        }
-    }
-
-    // Now that all ICDs have seen the message, call the necessary callbacks.  Ignoring "bail" return value
-    // as there is nothing to bail from at this point.
-
-    util_DebugReportMessage(inst, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
-
-    loader_platform_thread_unlock_mutex(&loader_lock);
-}
-
-bool debug_report_instance_gpa(struct loader_instance *ptr_instance, const char *name, void **addr) {
-    // debug_report is currently advertised to be supported by the loader,
-    // so always return the entry points if name matches and it's enabled
-    *addr = NULL;
-
-    if (!strcmp("vkCreateDebugReportCallbackEXT", name)) {
-        *addr = (ptr_instance->enabled_known_extensions.ext_debug_report == 1) ? (void *)debug_report_CreateDebugReportCallbackEXT
-                                                                               : NULL;
-        return true;
-    }
-    if (!strcmp("vkDestroyDebugReportCallbackEXT", name)) {
-        *addr = (ptr_instance->enabled_known_extensions.ext_debug_report == 1) ? (void *)debug_report_DestroyDebugReportCallbackEXT
-                                                                               : NULL;
-        return true;
-    }
-    if (!strcmp("vkDebugReportMessageEXT", name)) {
-        *addr = (ptr_instance->enabled_known_extensions.ext_debug_report == 1) ? (void *)debug_report_DebugReportMessageEXT : NULL;
-        return true;
-    }
-    return false;
-}
diff --git a/loader/debug_report.h b/loader/debug_report.h
deleted file mode 100644 (file)
index 89074d7..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (c) 2015-2016 The Khronos Group Inc.
- * Copyright (c) 2015-2016 Valve Corporation
- * Copyright (c) 2015-2016 LunarG, Inc.
- * Copyright (C) 2015-2016 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
- * Author: Jon Ashburn <jon@lunarg.com>
- *
- */
-
-#include "vk_loader_platform.h"
-#include "loader.h"
-
-// CreateMsgCallback is global and needs to be
-// applied to all layers and ICDs.
-// What happens if a layer is enabled on both the instance chain
-// as well as the device chain and a call to CreateMsgCallback is made?
-// Do we need to make sure that each layer / driver only gets called once?
-// Should a layer implementing support for CreateMsgCallback only be allowed (?)
-// to live on one chain? Or maybe make it the application's responsibility.
-// If the app enables DRAW_STATE on at both CreateInstance time and CreateDevice
-// time, CreateMsgCallback will call the DRAW_STATE layer twice. Once via
-// the instance chain and once via the device chain.
-// The loader should only return the DEBUG_REPORT extension as supported
-// for the GetGlobalExtensionSupport call. That should help eliminate one
-// duplication.
-// Since the instance chain requires us iterating over the available ICDs
-// and each ICD will have it's own unique MsgCallback object we need to
-// track those objects to give back the right one.
-// This also implies that the loader has to intercept vkDestroyObject and
-// if the extension is enabled and the object type is a MsgCallback then
-// we must translate the object into the proper ICD specific ones.
-// DestroyObject works on a device chain. Should not be what's destroying
-// the MsgCallback object. That needs to be an instance thing. So, since
-// we used an instance to create it, we need a custom Destroy that also
-// takes an instance. That way we can iterate over the ICDs properly.
-// Example use:
-// CreateInstance: DEBUG_REPORT
-//   Loader will create instance chain with enabled extensions.
-//   TODO: Should validation layers be enabled here? If not, they will not be in
-// the instance chain.
-// fn = GetProcAddr(INSTANCE, "vkCreateMsgCallback") -> point to loader's
-// vkCreateMsgCallback
-// App creates a callback object: fn(..., &MsgCallbackObject1)
-// Have only established the instance chain so far. Loader will call the
-// instance chain.
-// Each layer in the instance chain will call down to the next layer,
-// terminating with
-// the CreateMsgCallback loader terminator function that creates the actual
-// MsgCallbackObject1 object.
-// The loader CreateMsgCallback terminator will iterate over the ICDs.
-// Calling each ICD that supports vkCreateMsgCallback and collect answers in
-// icd_msg_callback_map here.
-// As result is sent back up the chain each layer has opportunity to record the
-// callback operation and
-// appropriate MsgCallback object.
-// ...
-// Any reports matching the flags set in MsgCallbackObject1 will generate the
-// defined callback behavior
-// in the layer / ICD that initiated that report.
-// ...
-// CreateDevice: MemTracker:...
-// App does not include DEBUG_REPORT as that is a global extension.
-// TODO: GetExtensionSupport must not report DEBUG_REPORT when using instance.
-// App MUST include any desired validation layers or they will not participate
-// in the device call chain.
-// App creates a callback object: fn(..., &MsgCallbackObject2)
-// Loader's vkCreateMsgCallback is called.
-// Loader sends call down instance chain - this is a global extension - any
-// validation layer that was
-// enabled at CreateInstance will be able to register the callback. Loader will
-// iterate over the ICDs and
-// will record the ICD's version of the MsgCallback2 object here.
-// ...
-// Any report will go to the layer's report function and it will check the flags
-// for MsgCallbackObject1
-// and MsgCallbackObject2 and take the appropriate action as indicated by the
-// app.
-// ...
-// App calls vkDestroyMsgCallback( MsgCallbackObject1 )
-// Loader's DestroyMsgCallback is where call starts. DestroyMsgCallback will be
-// sent down instance chain
-// ending in the loader's DestroyMsgCallback terminator which will iterate over
-// the ICD's destroying each
-// ICD version of that MsgCallback object and then destroy the loader's version
-// of the object.
-// Any reports generated after this will only have MsgCallbackObject2 available.
-
-void debug_report_add_instance_extensions(const struct loader_instance *inst, struct loader_extension_list *ext_list);
-
-void debug_report_create_instance(struct loader_instance *ptr_instance, const VkInstanceCreateInfo *pCreateInfo);
-
-bool debug_report_instance_gpa(struct loader_instance *ptr_instance, const char *name, void **addr);
-
-VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugReportCallbackEXT(VkInstance instance,
-                                                                       const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
-                                                                       const VkAllocationCallbacks *pAllocator,
-                                                                       VkDebugReportCallbackEXT *pCallback);
-
-VKAPI_ATTR void VKAPI_CALL terminator_DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
-                                                                    const VkAllocationCallbacks *pAllocator);
-
-VKAPI_ATTR void VKAPI_CALL terminator_DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags,
-                                                            VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location,
-                                                            int32_t msgCode, const char *pLayerPrefix, const char *pMsg);
-
-VkResult util_CreateDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
-                                        const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT callback);
-
-void util_DestroyDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackEXT callback,
-                                     const VkAllocationCallbacks *pAllocator);
-
-VkResult util_CopyDebugReportCreateInfos(const void *pChain, const VkAllocationCallbacks *pAllocator, uint32_t *num_callbacks,
-                                         VkDebugReportCallbackCreateInfoEXT **infos, VkDebugReportCallbackEXT **callbacks);
-void util_FreeDebugReportCreateInfos(const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackCreateInfoEXT *infos,
-                                     VkDebugReportCallbackEXT *callbacks);
-VkResult util_CreateDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator,
-                                         uint32_t num_callbacks, VkDebugReportCallbackCreateInfoEXT *infos,
-                                         VkDebugReportCallbackEXT *callbacks);
-
-void util_DestroyDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator, uint32_t num_callbacks,
-                                      VkDebugReportCallbackEXT *callbacks);
-
-VkBool32 util_DebugReportMessage(const struct loader_instance *inst, VkFlags msgFlags, VkDebugReportObjectTypeEXT objectType,
-                                 uint64_t srcObject, size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg);
diff --git a/loader/debug_utils.c b/loader/debug_utils.c
new file mode 100644 (file)
index 0000000..3689131
--- /dev/null
@@ -0,0 +1,1004 @@
+/*
+ * Copyright (c) 2015-2017 The Khronos Group Inc.
+ * Copyright (c) 2015-2017 Valve Corporation
+ * Copyright (c) 2015-2017 LunarG, Inc.
+ * Copyright (C) 2015-2016 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
+ * Author: Jon Ashburn <jon@LunarG.com>
+ * Author: Mark Young <marky@lunarg.com>
+ *
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#ifndef WIN32
+#include <signal.h>
+#else
+#endif
+#include "vk_loader_platform.h"
+#include "debug_utils.h"
+#include "vulkan/vk_layer.h"
+#include "vk_object_types.h"
+
+// VK_EXT_debug_report related items
+
+VkResult util_CreateDebugUtilsMessenger(struct loader_instance *inst, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
+                                        const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerEXT messenger) {
+    VkLayerDbgFunctionNode *pNewDbgFuncNode = NULL;
+
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+    {
+#else
+    if (pAllocator != NULL) {
+        pNewDbgFuncNode = (VkLayerDbgFunctionNode *)pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(VkLayerDbgFunctionNode),
+                                                                              sizeof(int *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+    } else {
+#endif
+        pNewDbgFuncNode = (VkLayerDbgFunctionNode *)loader_instance_heap_alloc(inst, sizeof(VkLayerDbgFunctionNode),
+                                                                               VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+    }
+    if (!pNewDbgFuncNode) {
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+    }
+    memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
+
+    pNewDbgFuncNode->is_messenger = true;
+    pNewDbgFuncNode->messenger.messenger = messenger;
+    pNewDbgFuncNode->messenger.pfnUserCallback = pCreateInfo->pfnUserCallback;
+    pNewDbgFuncNode->messenger.messageSeverity = pCreateInfo->messageSeverity;
+    pNewDbgFuncNode->messenger.messageType = pCreateInfo->messageType;
+    pNewDbgFuncNode->pUserData = pCreateInfo->pUserData;
+    pNewDbgFuncNode->pNext = inst->DbgFunctionHead;
+    inst->DbgFunctionHead = pNewDbgFuncNode;
+
+    return VK_SUCCESS;
+}
+
+static VKAPI_ATTR VkResult VKAPI_CALL
+debug_utils_CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
+                                         const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerEXT *pMessenger) {
+    struct loader_instance *inst = loader_get_instance(instance);
+    loader_platform_thread_lock_mutex(&loader_lock);
+    VkResult result = inst->disp->layer_inst_disp.CreateDebugUtilsMessengerEXT(instance, pCreateInfo, pAllocator, pMessenger);
+    loader_platform_thread_unlock_mutex(&loader_lock);
+    return result;
+}
+
+VkBool32 util_SubmitDebugUtilsMessageEXT(const struct loader_instance *inst, VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
+                                         VkDebugUtilsMessageTypeFlagsEXT messageTypes,
+                                         const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData) {
+    VkBool32 bail = false;
+
+    if (NULL != pCallbackData && NULL != pCallbackData->pObjects && 0 < pCallbackData->objectCount) {
+        VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead;
+        VkDebugReportObjectTypeEXT object_type;
+        VkDebugReportFlagsEXT object_flags = 0;
+        uint64_t object_handle;
+
+        debug_utils_AnnotFlagsToReportFlags(messageSeverity, messageTypes, &object_flags);
+        debug_utils_AnnotObjectToDebugReportObject(pCallbackData->pObjects, &object_type, &object_handle);
+
+        while (pTrav) {
+            if (pTrav->is_messenger && (pTrav->messenger.messageSeverity & messageSeverity) &&
+                (pTrav->messenger.messageType & messageTypes)) {
+                if (pTrav->messenger.pfnUserCallback(messageSeverity, messageTypes, pCallbackData, pTrav->pUserData)) {
+                    bail = true;
+                }
+            }
+            if (!pTrav->is_messenger && pTrav->report.msgFlags & object_flags) {
+                if (pTrav->report.pfnMsgCallback(object_flags, object_type, object_handle, 0, pCallbackData->messageIdNumber,
+                                                 pCallbackData->pMessageIdName, pCallbackData->pMessage, pTrav->pUserData)) {
+                    bail = true;
+                }
+            }
+
+            pTrav = pTrav->pNext;
+        }
+    }
+
+    return bail;
+}
+
+void util_DestroyDebugUtilsMessenger(struct loader_instance *inst, VkDebugUtilsMessengerEXT messenger,
+                                     const VkAllocationCallbacks *pAllocator) {
+    VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead;
+    VkLayerDbgFunctionNode *pPrev = pTrav;
+
+    while (pTrav) {
+        if (pTrav->is_messenger && pTrav->messenger.messenger == messenger) {
+            pPrev->pNext = pTrav->pNext;
+            if (inst->DbgFunctionHead == pTrav) inst->DbgFunctionHead = pTrav->pNext;
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+            {
+#else
+            if (pAllocator != NULL) {
+                pAllocator->pfnFree(pAllocator->pUserData, pTrav);
+            } else {
+#endif
+                loader_instance_heap_free(inst, pTrav);
+            }
+            break;
+        }
+        pPrev = pTrav;
+        pTrav = pTrav->pNext;
+    }
+}
+
+// This utility (used by vkInstanceCreateInfo(), looks at a pNext chain.  It
+// counts any VkDebugUtilsMessengerCreateInfoEXT structs that it finds.  It
+// then allocates array that can hold that many structs, as well as that many
+// VkDebugUtilsMessengerEXT handles.  It then copies each
+// VkDebugUtilsMessengerCreateInfoEXT, and initializes each handle.
+VkResult util_CopyDebugUtilsMessengerCreateInfos(const void *pChain, const VkAllocationCallbacks *pAllocator,
+                                                 uint32_t *num_messengers, VkDebugUtilsMessengerCreateInfoEXT **infos,
+                                                 VkDebugUtilsMessengerEXT **messengers) {
+    uint32_t n = *num_messengers = 0;
+    VkDebugUtilsMessengerCreateInfoEXT *pInfos = NULL;
+    VkDebugUtilsMessengerEXT *pMessengers = NULL;
+
+    const void *pNext = pChain;
+    while (pNext) {
+        // 1st, count the number VkDebugUtilsMessengerCreateInfoEXT:
+        if (((VkDebugUtilsMessengerCreateInfoEXT *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
+            n++;
+        }
+        pNext = (void *)((VkDebugUtilsMessengerCreateInfoEXT *)pNext)->pNext;
+    }
+    if (n == 0) {
+        return VK_SUCCESS;
+    }
+
+// 2nd, allocate memory for each VkDebugUtilsMessengerCreateInfoEXT:
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+    {
+#else
+    if (pAllocator != NULL) {
+        pInfos = *infos = ((VkDebugUtilsMessengerCreateInfoEXT *)pAllocator->pfnAllocation(
+            pAllocator->pUserData, n * sizeof(VkDebugUtilsMessengerCreateInfoEXT), sizeof(void *),
+            VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
+    } else {
+#endif
+        pInfos = *infos = ((VkDebugUtilsMessengerCreateInfoEXT *)malloc(n * sizeof(VkDebugUtilsMessengerCreateInfoEXT)));
+    }
+    if (!pInfos) {
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+    }
+// 3rd, allocate memory for a unique handle for each callback:
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+    {
+#else
+    if (pAllocator != NULL) {
+        pMessengers = *messengers = ((VkDebugUtilsMessengerEXT *)pAllocator->pfnAllocation(
+            pAllocator->pUserData, n * sizeof(VkDebugUtilsMessengerEXT), sizeof(void *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
+        if (NULL == pMessengers) {
+            pAllocator->pfnFree(pAllocator->pUserData, pInfos);
+            return VK_ERROR_OUT_OF_HOST_MEMORY;
+        }
+    } else {
+#endif
+        pMessengers = *messengers = ((VkDebugUtilsMessengerEXT *)malloc(n * sizeof(VkDebugUtilsMessengerEXT)));
+        if (NULL == pMessengers) {
+            free(pInfos);
+            return VK_ERROR_OUT_OF_HOST_MEMORY;
+        }
+    }
+    // 4th, copy each VkDebugUtilsMessengerCreateInfoEXT for use by
+    // vkDestroyInstance, and assign a unique handle to each messenger (just
+    // use the address of the copied VkDebugUtilsMessengerCreateInfoEXT):
+    pNext = pChain;
+    while (pNext) {
+        if (((VkInstanceCreateInfo *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
+            memcpy(pInfos, pNext, sizeof(VkDebugUtilsMessengerCreateInfoEXT));
+            *pMessengers++ = (VkDebugUtilsMessengerEXT)(uintptr_t)pInfos++;
+        }
+        pNext = (void *)((VkInstanceCreateInfo *)pNext)->pNext;
+    }
+
+    *num_messengers = n;
+    return VK_SUCCESS;
+}
+
+void util_FreeDebugUtilsMessengerCreateInfos(const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerCreateInfoEXT *infos,
+                                             VkDebugUtilsMessengerEXT *messengers) {
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+    {
+#else
+    if (pAllocator != NULL) {
+        pAllocator->pfnFree(pAllocator->pUserData, infos);
+        pAllocator->pfnFree(pAllocator->pUserData, messengers);
+    } else {
+#endif
+        free(infos);
+        free(messengers);
+    }
+}
+
+VkResult util_CreateDebugUtilsMessengers(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator,
+                                         uint32_t num_messengers, VkDebugUtilsMessengerCreateInfoEXT *infos,
+                                         VkDebugUtilsMessengerEXT *messengers) {
+    VkResult rtn = VK_SUCCESS;
+    for (uint32_t i = 0; i < num_messengers; i++) {
+        rtn = util_CreateDebugUtilsMessenger(inst, &infos[i], pAllocator, messengers[i]);
+        if (rtn != VK_SUCCESS) {
+            for (uint32_t j = 0; j < i; j++) {
+                util_DestroyDebugUtilsMessenger(inst, messengers[j], pAllocator);
+            }
+            return rtn;
+        }
+    }
+    return rtn;
+}
+
+void util_DestroyDebugUtilsMessengers(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator,
+                                      uint32_t num_messengers, VkDebugUtilsMessengerEXT *messengers) {
+    for (uint32_t i = 0; i < num_messengers; i++) {
+        util_DestroyDebugUtilsMessenger(inst, messengers[i], pAllocator);
+    }
+}
+
+static VKAPI_ATTR void VKAPI_CALL debug_utils_SubmitDebugUtilsMessageEXT(
+    VkInstance instance, VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageTypes,
+    const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData) {
+    struct loader_instance *inst = loader_get_instance(instance);
+
+    inst->disp->layer_inst_disp.SubmitDebugUtilsMessageEXT(instance, messageSeverity, messageTypes, pCallbackData);
+}
+
+static VKAPI_ATTR void VKAPI_CALL debug_utils_DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger,
+                                                                            const VkAllocationCallbacks *pAllocator) {
+    struct loader_instance *inst = loader_get_instance(instance);
+    loader_platform_thread_lock_mutex(&loader_lock);
+
+    inst->disp->layer_inst_disp.DestroyDebugUtilsMessengerEXT(instance, messenger, pAllocator);
+
+    util_DestroyDebugUtilsMessenger(inst, messenger, pAllocator);
+
+    loader_platform_thread_unlock_mutex(&loader_lock);
+}
+
+// This is the instance chain terminator function for CreateDebugUtilsMessenger
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugUtilsMessengerEXT(VkInstance instance,
+                                                                       const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
+                                                                       const VkAllocationCallbacks *pAllocator,
+                                                                       VkDebugUtilsMessengerEXT *pMessenger) {
+    VkDebugUtilsMessengerEXT *icd_info = NULL;
+    const struct loader_icd_term *icd_term;
+    struct loader_instance *inst = (struct loader_instance *)instance;
+    VkResult res = VK_SUCCESS;
+    uint32_t storage_idx;
+    VkLayerDbgFunctionNode *pNewDbgFuncNode = NULL;
+
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+    {
+#else
+    if (pAllocator != NULL) {
+        icd_info = ((VkDebugUtilsMessengerEXT *)pAllocator->pfnAllocation(pAllocator->pUserData,
+                                                                          inst->total_icd_count * sizeof(VkDebugUtilsMessengerEXT),
+                                                                          sizeof(void *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
+        if (icd_info) {
+            memset(icd_info, 0, inst->total_icd_count * sizeof(VkDebugUtilsMessengerEXT));
+        }
+    } else {
+#endif
+        icd_info = calloc(sizeof(VkDebugUtilsMessengerEXT), inst->total_icd_count);
+    }
+    if (!icd_info) {
+        res = VK_ERROR_OUT_OF_HOST_MEMORY;
+        goto out;
+    }
+
+    storage_idx = 0;
+    for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
+        if (!icd_term->dispatch.CreateDebugUtilsMessengerEXT) {
+            continue;
+        }
+
+        res = icd_term->dispatch.CreateDebugUtilsMessengerEXT(icd_term->instance, pCreateInfo, pAllocator, &icd_info[storage_idx]);
+
+        if (res != VK_SUCCESS) {
+            goto out;
+        }
+        storage_idx++;
+    }
+
+// Setup the debug report callback in the terminator since a layer may want
+// to grab the information itself (RenderDoc) and then return back to the
+// user callback a sub-set of the messages.
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 0)
+    if (pAllocator != NULL) {
+        pNewDbgFuncNode = (VkLayerDbgFunctionNode *)pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(VkLayerDbgFunctionNode),
+                                                                              sizeof(int *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+    } else {
+#else
+    {
+#endif
+        pNewDbgFuncNode = (VkLayerDbgFunctionNode *)loader_instance_heap_alloc(inst, sizeof(VkLayerDbgFunctionNode),
+                                                                               VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+    }
+    if (!pNewDbgFuncNode) {
+        res = VK_ERROR_OUT_OF_HOST_MEMORY;
+        goto out;
+    }
+    memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
+
+    pNewDbgFuncNode->is_messenger = true;
+    pNewDbgFuncNode->messenger.pfnUserCallback = pCreateInfo->pfnUserCallback;
+    pNewDbgFuncNode->messenger.messageSeverity = pCreateInfo->messageSeverity;
+    pNewDbgFuncNode->messenger.messageType = pCreateInfo->messageType;
+    pNewDbgFuncNode->pUserData = pCreateInfo->pUserData;
+    pNewDbgFuncNode->pNext = inst->DbgFunctionHead;
+    inst->DbgFunctionHead = pNewDbgFuncNode;
+
+    *(VkDebugUtilsMessengerEXT **)pMessenger = icd_info;
+    pNewDbgFuncNode->messenger.messenger = *pMessenger;
+
+out:
+
+    // Roll back on errors
+    if (VK_SUCCESS != res) {
+        storage_idx = 0;
+        for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
+            if (NULL == icd_term->dispatch.DestroyDebugUtilsMessengerEXT) {
+                continue;
+            }
+
+            if (icd_info && icd_info[storage_idx]) {
+                icd_term->dispatch.DestroyDebugUtilsMessengerEXT(icd_term->instance, icd_info[storage_idx], pAllocator);
+            }
+            storage_idx++;
+        }
+
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+        {
+#else
+        if (pAllocator != NULL) {
+            if (NULL != pNewDbgFuncNode) {
+                pAllocator->pfnFree(pAllocator->pUserData, pNewDbgFuncNode);
+            }
+            if (NULL != icd_info) {
+                pAllocator->pfnFree(pAllocator->pUserData, icd_info);
+            }
+        } else {
+#endif
+            if (NULL != pNewDbgFuncNode) {
+                free(pNewDbgFuncNode);
+            }
+            if (NULL != icd_info) {
+                free(icd_info);
+            }
+        }
+    }
+
+    return res;
+}
+
+// This is the instance chain terminator function for DestroyDebugUtilsMessenger
+VKAPI_ATTR void VKAPI_CALL terminator_DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger,
+                                                                    const VkAllocationCallbacks *pAllocator) {
+    uint32_t storage_idx;
+    VkDebugUtilsMessengerEXT *icd_info;
+    const struct loader_icd_term *icd_term;
+
+    struct loader_instance *inst = (struct loader_instance *)instance;
+    icd_info = *(VkDebugUtilsMessengerEXT **)&messenger;
+    storage_idx = 0;
+    for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
+        if (NULL == icd_term->dispatch.DestroyDebugUtilsMessengerEXT) {
+            continue;
+        }
+
+        if (icd_info[storage_idx]) {
+            icd_term->dispatch.DestroyDebugUtilsMessengerEXT(icd_term->instance, icd_info[storage_idx], pAllocator);
+        }
+        storage_idx++;
+    }
+
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+    {
+#else
+    if (pAllocator != NULL) {
+        pAllocator->pfnFree(pAllocator->pUserData, icd_info);
+    } else {
+#endif
+        free(icd_info);
+    }
+}
+
+// This is the instance chain terminator function for SubmitDebugUtilsMessageEXT
+VKAPI_ATTR void VKAPI_CALL terminator_SubmitDebugUtilsMessageEXT(VkInstance instance,
+                                                                 VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
+                                                                 VkDebugUtilsMessageTypeFlagsEXT messageTypes,
+                                                                 const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData) {
+    const struct loader_icd_term *icd_term;
+
+    struct loader_instance *inst = (struct loader_instance *)instance;
+
+    loader_platform_thread_lock_mutex(&loader_lock);
+    for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
+        if (icd_term->dispatch.SubmitDebugUtilsMessageEXT != NULL) {
+            icd_term->dispatch.SubmitDebugUtilsMessageEXT(icd_term->instance, messageSeverity, messageTypes, pCallbackData);
+        }
+    }
+
+    // Now that all ICDs have seen the message, call the necessary callbacks.  Ignoring "bail" return value
+    // as there is nothing to bail from at this point.
+
+    util_SubmitDebugUtilsMessageEXT(inst, messageSeverity, messageTypes, pCallbackData);
+
+    loader_platform_thread_unlock_mutex(&loader_lock);
+}
+
+// VK_EXT_debug_report related items
+
+VkResult util_CreateDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
+                                        const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT callback) {
+    VkLayerDbgFunctionNode *pNewDbgFuncNode = NULL;
+
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+    {
+#else
+    if (pAllocator != NULL) {
+        pNewDbgFuncNode = (VkLayerDbgFunctionNode *)pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(VkLayerDbgFunctionNode),
+                                                                              sizeof(int *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+    } else {
+#endif
+        pNewDbgFuncNode = (VkLayerDbgFunctionNode *)loader_instance_heap_alloc(inst, sizeof(VkLayerDbgFunctionNode),
+                                                                               VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+    }
+    if (!pNewDbgFuncNode) {
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+    }
+    memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
+
+    pNewDbgFuncNode->is_messenger = false;
+    pNewDbgFuncNode->report.msgCallback = callback;
+    pNewDbgFuncNode->report.pfnMsgCallback = pCreateInfo->pfnCallback;
+    pNewDbgFuncNode->report.msgFlags = pCreateInfo->flags;
+    pNewDbgFuncNode->pUserData = pCreateInfo->pUserData;
+    pNewDbgFuncNode->pNext = inst->DbgFunctionHead;
+    inst->DbgFunctionHead = pNewDbgFuncNode;
+
+    return VK_SUCCESS;
+}
+
+static VKAPI_ATTR VkResult VKAPI_CALL
+debug_utils_CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
+                                         const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pCallback) {
+    struct loader_instance *inst = loader_get_instance(instance);
+    loader_platform_thread_lock_mutex(&loader_lock);
+    VkResult result = inst->disp->layer_inst_disp.CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
+    loader_platform_thread_unlock_mutex(&loader_lock);
+    return result;
+}
+
+// Utility function to handle reporting
+VkBool32 util_DebugReportMessage(const struct loader_instance *inst, VkFlags msgFlags, VkDebugReportObjectTypeEXT objectType,
+                                 uint64_t srcObject, size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
+    VkBool32 bail = false;
+    VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead;
+    VkDebugUtilsMessageSeverityFlagBitsEXT severity;
+    VkDebugUtilsMessageTypeFlagsEXT types;
+    VkDebugUtilsMessengerCallbackDataEXT callback_data;
+    VkDebugUtilsObjectNameInfoEXT object_name;
+
+    debug_utils_ReportFlagsToAnnotFlags(msgFlags, false, &severity, &types);
+    debug_utils_ReportObjectToAnnotObject(objectType, srcObject, &object_name);
+
+    callback_data.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT;
+    callback_data.pNext = NULL;
+    callback_data.flags = 0;
+    callback_data.pMessageIdName = pLayerPrefix;
+    callback_data.messageIdNumber = msgCode;
+    callback_data.pMessage = pMsg;
+    callback_data.cmdBufLabelCount = 0;
+    callback_data.pCmdBufLabels = NULL;
+    callback_data.queueLabelCount = 0;
+    callback_data.pQueueLabels = NULL;
+    callback_data.objectCount = 1;
+    callback_data.pObjects = &object_name;
+
+    while (pTrav) {
+        if (!pTrav->is_messenger && pTrav->report.msgFlags & msgFlags) {
+            if (pTrav->report.pfnMsgCallback(msgFlags, objectType, srcObject, location, msgCode, pLayerPrefix, pMsg,
+                                             pTrav->pUserData)) {
+                bail = true;
+            }
+        }
+        if (pTrav->is_messenger && (pTrav->messenger.messageSeverity & severity) && (pTrav->messenger.messageType & types)) {
+            if (pTrav->messenger.pfnUserCallback(severity, types, &callback_data, pTrav->pUserData)) {
+                bail = true;
+            }
+        }
+
+        pTrav = pTrav->pNext;
+    }
+
+    return bail;
+}
+
+void util_DestroyDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackEXT callback,
+                                     const VkAllocationCallbacks *pAllocator) {
+    VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead;
+    VkLayerDbgFunctionNode *pPrev = pTrav;
+
+    while (pTrav) {
+        if (!pTrav->is_messenger && pTrav->report.msgCallback == callback) {
+            pPrev->pNext = pTrav->pNext;
+            if (inst->DbgFunctionHead == pTrav) inst->DbgFunctionHead = pTrav->pNext;
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+            {
+#else
+            if (pAllocator != NULL) {
+                pAllocator->pfnFree(pAllocator->pUserData, pTrav);
+            } else {
+#endif
+                loader_instance_heap_free(inst, pTrav);
+            }
+            break;
+        }
+        pPrev = pTrav;
+        pTrav = pTrav->pNext;
+    }
+}
+
+// This utility (used by vkInstanceCreateInfo(), looks at a pNext chain.  It
+// counts any VkDebugReportCallbackCreateInfoEXT structs that it finds.  It
+// then allocates array that can hold that many structs, as well as that many
+// VkDebugReportCallbackEXT handles.  It then copies each
+// VkDebugReportCallbackCreateInfoEXT, and initializes each handle.
+VkResult util_CopyDebugReportCreateInfos(const void *pChain, const VkAllocationCallbacks *pAllocator, uint32_t *num_callbacks,
+                                         VkDebugReportCallbackCreateInfoEXT **infos, VkDebugReportCallbackEXT **callbacks) {
+    uint32_t n = *num_callbacks = 0;
+    VkDebugReportCallbackCreateInfoEXT *pInfos = NULL;
+    VkDebugReportCallbackEXT *pCallbacks = NULL;
+
+    const void *pNext = pChain;
+    while (pNext) {
+        // 1st, count the number VkDebugReportCallbackCreateInfoEXT:
+        if (((VkDebugReportCallbackCreateInfoEXT *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
+            n++;
+        }
+        pNext = (void *)((VkDebugReportCallbackCreateInfoEXT *)pNext)->pNext;
+    }
+    if (n == 0) {
+        return VK_SUCCESS;
+    }
+
+// 2nd, allocate memory for each VkDebugReportCallbackCreateInfoEXT:
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+    {
+#else
+    if (pAllocator != NULL) {
+        pInfos = *infos = ((VkDebugReportCallbackCreateInfoEXT *)pAllocator->pfnAllocation(
+            pAllocator->pUserData, n * sizeof(VkDebugReportCallbackCreateInfoEXT), sizeof(void *),
+            VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
+    } else {
+#endif
+        pInfos = *infos = ((VkDebugReportCallbackCreateInfoEXT *)malloc(n * sizeof(VkDebugReportCallbackCreateInfoEXT)));
+    }
+    if (!pInfos) {
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+    }
+// 3rd, allocate memory for a unique handle for each callback:
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+    {
+#else
+    if (pAllocator != NULL) {
+        pCallbacks = *callbacks = ((VkDebugReportCallbackEXT *)pAllocator->pfnAllocation(
+            pAllocator->pUserData, n * sizeof(VkDebugReportCallbackEXT), sizeof(void *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
+        if (!pCallbacks) {
+            pAllocator->pfnFree(pAllocator->pUserData, pInfos);
+            return VK_ERROR_OUT_OF_HOST_MEMORY;
+        }
+    } else {
+#endif
+        pCallbacks = *callbacks = ((VkDebugReportCallbackEXT *)malloc(n * sizeof(VkDebugReportCallbackEXT)));
+        if (!pCallbacks) {
+            free(pInfos);
+            return VK_ERROR_OUT_OF_HOST_MEMORY;
+        }
+    }
+    // 4th, copy each VkDebugReportCallbackCreateInfoEXT for use by
+    // vkDestroyInstance, and assign a unique handle to each callback (just
+    // use the address of the copied VkDebugReportCallbackCreateInfoEXT):
+    pNext = pChain;
+    while (pNext) {
+        if (((VkInstanceCreateInfo *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
+            memcpy(pInfos, pNext, sizeof(VkDebugReportCallbackCreateInfoEXT));
+            *pCallbacks++ = (VkDebugReportCallbackEXT)(uintptr_t)pInfos++;
+        }
+        pNext = (void *)((VkInstanceCreateInfo *)pNext)->pNext;
+    }
+
+    *num_callbacks = n;
+    return VK_SUCCESS;
+}
+
+void util_FreeDebugReportCreateInfos(const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackCreateInfoEXT *infos,
+                                     VkDebugReportCallbackEXT *callbacks) {
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+    {
+#else
+    if (pAllocator != NULL) {
+        pAllocator->pfnFree(pAllocator->pUserData, infos);
+        pAllocator->pfnFree(pAllocator->pUserData, callbacks);
+    } else {
+#endif
+        free(infos);
+        free(callbacks);
+    }
+}
+
+VkResult util_CreateDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator,
+                                         uint32_t num_callbacks, VkDebugReportCallbackCreateInfoEXT *infos,
+                                         VkDebugReportCallbackEXT *callbacks) {
+    VkResult rtn = VK_SUCCESS;
+    for (uint32_t i = 0; i < num_callbacks; i++) {
+        rtn = util_CreateDebugReportCallback(inst, &infos[i], pAllocator, callbacks[i]);
+        if (rtn != VK_SUCCESS) {
+            for (uint32_t j = 0; j < i; j++) {
+                util_DestroyDebugReportCallback(inst, callbacks[j], pAllocator);
+            }
+            return rtn;
+        }
+    }
+    return rtn;
+}
+
+void util_DestroyDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator, uint32_t num_callbacks,
+                                      VkDebugReportCallbackEXT *callbacks) {
+    for (uint32_t i = 0; i < num_callbacks; i++) {
+        util_DestroyDebugReportCallback(inst, callbacks[i], pAllocator);
+    }
+}
+
+static VKAPI_ATTR void VKAPI_CALL debug_utils_DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
+                                                                            const VkAllocationCallbacks *pAllocator) {
+    struct loader_instance *inst = loader_get_instance(instance);
+    loader_platform_thread_lock_mutex(&loader_lock);
+
+    inst->disp->layer_inst_disp.DestroyDebugReportCallbackEXT(instance, callback, pAllocator);
+
+    util_DestroyDebugReportCallback(inst, callback, pAllocator);
+
+    loader_platform_thread_unlock_mutex(&loader_lock);
+}
+
+static VKAPI_ATTR void VKAPI_CALL debug_utils_DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags,
+                                                                    VkDebugReportObjectTypeEXT objType, uint64_t object,
+                                                                    size_t location, int32_t msgCode, const char *pLayerPrefix,
+                                                                    const char *pMsg) {
+    struct loader_instance *inst = loader_get_instance(instance);
+
+    inst->disp->layer_inst_disp.DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
+}
+
+// This is the instance chain terminator function
+// for CreateDebugReportCallback
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugReportCallbackEXT(VkInstance instance,
+                                                                       const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
+                                                                       const VkAllocationCallbacks *pAllocator,
+                                                                       VkDebugReportCallbackEXT *pCallback) {
+    VkDebugReportCallbackEXT *icd_info = NULL;
+    const struct loader_icd_term *icd_term;
+    struct loader_instance *inst = (struct loader_instance *)instance;
+    VkResult res = VK_SUCCESS;
+    uint32_t storage_idx;
+    VkLayerDbgFunctionNode *pNewDbgFuncNode = NULL;
+
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+    {
+#else
+    if (pAllocator != NULL) {
+        icd_info = ((VkDebugReportCallbackEXT *)pAllocator->pfnAllocation(pAllocator->pUserData,
+                                                                          inst->total_icd_count * sizeof(VkDebugReportCallbackEXT),
+                                                                          sizeof(void *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
+        if (icd_info) {
+            memset(icd_info, 0, inst->total_icd_count * sizeof(VkDebugReportCallbackEXT));
+        }
+    } else {
+#endif
+        icd_info = calloc(sizeof(VkDebugReportCallbackEXT), inst->total_icd_count);
+    }
+    if (!icd_info) {
+        res = VK_ERROR_OUT_OF_HOST_MEMORY;
+        goto out;
+    }
+
+    storage_idx = 0;
+    for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
+        if (!icd_term->dispatch.CreateDebugReportCallbackEXT) {
+            continue;
+        }
+
+        res = icd_term->dispatch.CreateDebugReportCallbackEXT(icd_term->instance, pCreateInfo, pAllocator, &icd_info[storage_idx]);
+
+        if (res != VK_SUCCESS) {
+            goto out;
+        }
+        storage_idx++;
+    }
+
+// Setup the debug report callback in the terminator since a layer may want
+// to grab the information itself (RenderDoc) and then return back to the
+// user callback a sub-set of the messages.
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 0)
+    if (pAllocator != NULL) {
+        pNewDbgFuncNode = (VkLayerDbgFunctionNode *)pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(VkLayerDbgFunctionNode),
+                                                                              sizeof(int *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+    } else {
+#else
+    {
+#endif
+        pNewDbgFuncNode = (VkLayerDbgFunctionNode *)loader_instance_heap_alloc(inst, sizeof(VkLayerDbgFunctionNode),
+                                                                               VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+    }
+    if (!pNewDbgFuncNode) {
+        res = VK_ERROR_OUT_OF_HOST_MEMORY;
+        goto out;
+    }
+    memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
+
+    pNewDbgFuncNode->is_messenger = false;
+    pNewDbgFuncNode->report.pfnMsgCallback = pCreateInfo->pfnCallback;
+    pNewDbgFuncNode->report.msgFlags = pCreateInfo->flags;
+    pNewDbgFuncNode->pUserData = pCreateInfo->pUserData;
+    pNewDbgFuncNode->pNext = inst->DbgFunctionHead;
+    inst->DbgFunctionHead = pNewDbgFuncNode;
+
+    *(VkDebugReportCallbackEXT **)pCallback = icd_info;
+    pNewDbgFuncNode->report.msgCallback = *pCallback;
+
+out:
+
+    // Roll back on errors
+    if (VK_SUCCESS != res) {
+        storage_idx = 0;
+        for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
+            if (NULL == icd_term->dispatch.DestroyDebugReportCallbackEXT) {
+                continue;
+            }
+
+            if (icd_info && icd_info[storage_idx]) {
+                icd_term->dispatch.DestroyDebugReportCallbackEXT(icd_term->instance, icd_info[storage_idx], pAllocator);
+            }
+            storage_idx++;
+        }
+
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+        {
+#else
+        if (pAllocator != NULL) {
+            if (NULL != pNewDbgFuncNode) {
+                pAllocator->pfnFree(pAllocator->pUserData, pNewDbgFuncNode);
+            }
+            if (NULL != icd_info) {
+                pAllocator->pfnFree(pAllocator->pUserData, icd_info);
+            }
+        } else {
+#endif
+            if (NULL != pNewDbgFuncNode) {
+                free(pNewDbgFuncNode);
+            }
+            if (NULL != icd_info) {
+                free(icd_info);
+            }
+        }
+    }
+
+    return res;
+}
+
+// This is the instance chain terminator function for DestroyDebugReportCallback
+VKAPI_ATTR void VKAPI_CALL terminator_DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
+                                                                    const VkAllocationCallbacks *pAllocator) {
+    uint32_t storage_idx;
+    VkDebugReportCallbackEXT *icd_info;
+    const struct loader_icd_term *icd_term;
+
+    struct loader_instance *inst = (struct loader_instance *)instance;
+    icd_info = *(VkDebugReportCallbackEXT **)&callback;
+    storage_idx = 0;
+    for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
+        if (NULL == icd_term->dispatch.DestroyDebugReportCallbackEXT) {
+            continue;
+        }
+
+        if (icd_info[storage_idx]) {
+            icd_term->dispatch.DestroyDebugReportCallbackEXT(icd_term->instance, icd_info[storage_idx], pAllocator);
+        }
+        storage_idx++;
+    }
+
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+    {
+#else
+    if (pAllocator != NULL) {
+        pAllocator->pfnFree(pAllocator->pUserData, icd_info);
+    } else {
+#endif
+        free(icd_info);
+    }
+}
+
+// This is the instance chain terminator function for DebugReportMessage
+VKAPI_ATTR void VKAPI_CALL terminator_DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags,
+                                                            VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location,
+                                                            int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
+    const struct loader_icd_term *icd_term;
+
+    struct loader_instance *inst = (struct loader_instance *)instance;
+
+    loader_platform_thread_lock_mutex(&loader_lock);
+    for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
+        if (icd_term->dispatch.DebugReportMessageEXT != NULL) {
+            icd_term->dispatch.DebugReportMessageEXT(icd_term->instance, flags, objType, object, location, msgCode, pLayerPrefix,
+                                                     pMsg);
+        }
+    }
+
+    // Now that all ICDs have seen the message, call the necessary callbacks.  Ignoring "bail" return value
+    // as there is nothing to bail from at this point.
+
+    util_DebugReportMessage(inst, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
+
+    loader_platform_thread_unlock_mutex(&loader_lock);
+}
+
+// General utilities
+
+static const VkExtensionProperties debug_utils_extension_info[] = {
+    {VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION},
+    {VK_EXT_DEBUG_UTILS_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_SPEC_VERSION},
+};
+
+void debug_utils_AddInstanceExtensions(const struct loader_instance *inst, struct loader_extension_list *ext_list) {
+    loader_add_to_ext_list(inst, ext_list, sizeof(debug_utils_extension_info) / sizeof(VkExtensionProperties),
+                           debug_utils_extension_info);
+}
+
+void debug_utils_CreateInstance(struct loader_instance *ptr_instance, const VkInstanceCreateInfo *pCreateInfo) {
+    ptr_instance->enabled_known_extensions.ext_debug_report = 0;
+    ptr_instance->enabled_known_extensions.ext_debug_utils = 0;
+
+    for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
+        if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0) {
+            ptr_instance->enabled_known_extensions.ext_debug_report = 1;
+        } else if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_EXT_DEBUG_UTILS_EXTENSION_NAME) == 0) {
+            ptr_instance->enabled_known_extensions.ext_debug_utils = 1;
+        }
+    }
+}
+
+bool debug_utils_InstanceGpa(struct loader_instance *ptr_instance, const char *name, void **addr) {
+    bool ret_type = false;
+
+    *addr = NULL;
+
+    if (ptr_instance->enabled_known_extensions.ext_debug_report == 1) {
+        if (!strcmp("vkCreateDebugReportCallbackEXT", name)) {
+            *addr = (void *)debug_utils_CreateDebugReportCallbackEXT;
+            ret_type = true;
+        } else if (!strcmp("vkDestroyDebugReportCallbackEXT", name)) {
+            *addr = (void *)debug_utils_DestroyDebugReportCallbackEXT;
+            ret_type = true;
+        } else if (!strcmp("vkDebugReportMessageEXT", name)) {
+            *addr = (void *)debug_utils_DebugReportMessageEXT;
+            return true;
+        }
+    }
+    if (ptr_instance->enabled_known_extensions.ext_debug_utils == 1) {
+        if (!strcmp("vkCreateDebugUtilsMessengerEXT", name)) {
+            *addr = (void *)debug_utils_CreateDebugUtilsMessengerEXT;
+            ret_type = true;
+        } else if (!strcmp("vkDestroyDebugUtilsMessengerEXT", name)) {
+            *addr = (void *)debug_utils_DestroyDebugUtilsMessengerEXT;
+            ret_type = true;
+        } else if (!strcmp("vkSubmitDebugUtilsMessageEXT", name)) {
+            *addr = (void *)debug_utils_SubmitDebugUtilsMessageEXT;
+            ret_type = true;
+        }
+    }
+
+    return ret_type;
+}
+
+bool debug_utils_ReportFlagsToAnnotFlags(VkDebugReportFlagsEXT dr_flags, bool default_flag_is_spec,
+                                         VkDebugUtilsMessageSeverityFlagBitsEXT *da_severity,
+                                         VkDebugUtilsMessageTypeFlagsEXT *da_type) {
+    bool type_set = false;
+    if (NULL == da_severity || NULL == da_type) {
+        return false;
+    }
+    *da_type = 0;
+
+    if ((dr_flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) != 0) {
+        *da_severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
+        *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
+        type_set = true;
+    } else if ((dr_flags & (VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT)) != 0) {
+        *da_severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
+    } else if ((dr_flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) != 0) {
+        *da_severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
+    } else if ((dr_flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) != 0) {
+        *da_severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
+        *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
+        type_set = true;
+    }
+
+    if ((dr_flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) != 0) {
+        *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
+    } else if (!type_set) {
+        if (default_flag_is_spec) {
+            *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
+        } else {
+            *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
+        }
+    }
+
+    return true;
+}
+
+bool debug_utils_AnnotFlagsToReportFlags(VkDebugUtilsMessageSeverityFlagBitsEXT da_severity,
+                                         VkDebugUtilsMessageTypeFlagsEXT da_type, VkDebugReportFlagsEXT *dr_flags) {
+    if (NULL == dr_flags) {
+        return false;
+    }
+
+    *dr_flags = 0;
+
+    if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) != 0) {
+        *dr_flags |= VK_DEBUG_REPORT_ERROR_BIT_EXT;
+    } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) != 0) {
+        if ((da_type & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) != 0) {
+            *dr_flags |= VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
+        } else {
+            *dr_flags |= VK_DEBUG_REPORT_WARNING_BIT_EXT;
+        }
+    } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) != 0) {
+        *dr_flags |= VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
+    } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) != 0) {
+        *dr_flags |= VK_DEBUG_REPORT_DEBUG_BIT_EXT;
+    }
+
+    return true;
+}
+
+bool debug_utils_ReportObjectToAnnotObject(VkDebugReportObjectTypeEXT dr_object_type, uint64_t object_handle,
+                                           VkDebugUtilsObjectNameInfoEXT *da_object_name_info) {
+    if (NULL == da_object_name_info) {
+        return false;
+    }
+    da_object_name_info->sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
+    da_object_name_info->pNext = NULL;
+    da_object_name_info->objectHandle = (uint64_t)(uintptr_t)object_handle;
+    da_object_name_info->pObjectName = NULL;
+    da_object_name_info->objectType = convertDebugReportObjectToCoreObject(dr_object_type);
+    return true;
+}
+
+bool debug_utils_AnnotObjectToDebugReportObject(const VkDebugUtilsObjectNameInfoEXT *da_object_name_info,
+                                                VkDebugReportObjectTypeEXT *dr_object_type, uint64_t *dr_object_handle) {
+    if (NULL == da_object_name_info || NULL == dr_object_type || NULL == dr_object_handle) {
+        return false;
+    }
+    *dr_object_type = convertCoreObjectToDebugReportObject(da_object_name_info->objectType);
+    *dr_object_handle = da_object_name_info->objectHandle;
+    return true;
+}
diff --git a/loader/debug_utils.h b/loader/debug_utils.h
new file mode 100644 (file)
index 0000000..c33a6fc
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2015-2017 The Khronos Group Inc.
+ * Copyright (c) 2015-2017 Valve Corporation
+ * Copyright (c) 2015-2017 LunarG, Inc.
+ * Copyright (C) 2015-2016 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
+ * Author: Jon Ashburn <jon@lunarg.com>
+ * Author: Mark Young <markyk@lunarg.com>
+ *
+ */
+
+#include "vk_loader_platform.h"
+#include "loader.h"
+
+// General utilities
+
+void debug_utils_AddInstanceExtensions(const struct loader_instance *inst, struct loader_extension_list *ext_list);
+void debug_utils_CreateInstance(struct loader_instance *ptr_instance, const VkInstanceCreateInfo *pCreateInfo);
+bool debug_utils_InstanceGpa(struct loader_instance *ptr_instance, const char *name, void **addr);
+bool debug_utils_ReportFlagsToAnnotFlags(VkDebugReportFlagsEXT dr_flags, bool default_flag_is_spec,
+                                         VkDebugUtilsMessageSeverityFlagBitsEXT *da_severity,
+                                         VkDebugUtilsMessageTypeFlagsEXT *da_type);
+bool debug_utils_AnnotFlagsToReportFlags(VkDebugUtilsMessageSeverityFlagBitsEXT da_severity,
+                                         VkDebugUtilsMessageTypeFlagsEXT da_type, VkDebugReportFlagsEXT *dr_flags);
+bool debug_utils_ReportObjectToAnnotObject(VkDebugReportObjectTypeEXT dr_object_type, uint64_t object_handle,
+                                           VkDebugUtilsObjectNameInfoEXT *da_object_name_info);
+bool debug_utils_AnnotObjectToDebugReportObject(const VkDebugUtilsObjectNameInfoEXT *da_object_name_info,
+                                                VkDebugReportObjectTypeEXT *dr_object_type, uint64_t *dr_object_handle);
+
+// VK_EXT_debug_utils related items
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugUtilsMessengerEXT(VkInstance instance,
+                                                                       const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
+                                                                       const VkAllocationCallbacks *pAllocator,
+                                                                       VkDebugUtilsMessengerEXT *pMessenger);
+VKAPI_ATTR void VKAPI_CALL terminator_DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger,
+                                                                    const VkAllocationCallbacks *pAllocator);
+VKAPI_ATTR void VKAPI_CALL terminator_SubmitDebugUtilsMessageEXT(VkInstance instance,
+                                                                 VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
+                                                                 VkDebugUtilsMessageTypeFlagsEXT messageTypes,
+                                                                 const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData);
+VkResult util_CreateDebugUtilsMessenger(struct loader_instance *inst, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
+                                        const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerEXT messenger);
+VkResult util_CreateDebugUtilsMessengers(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator,
+                                         uint32_t num_messengers, VkDebugUtilsMessengerCreateInfoEXT *infos,
+                                         VkDebugUtilsMessengerEXT *messengers);
+VkBool32 util_SubmitDebugUtilsMessageEXT(const struct loader_instance *inst, VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
+                                         VkDebugUtilsMessageTypeFlagsEXT messageTypes,
+                                         const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData);
+VkResult util_CopyDebugUtilsMessengerCreateInfos(const void *pChain, const VkAllocationCallbacks *pAllocator,
+                                                 uint32_t *num_messengers, VkDebugUtilsMessengerCreateInfoEXT **infos,
+                                                 VkDebugUtilsMessengerEXT **messengers);
+void util_DestroyDebugUtilsMessenger(struct loader_instance *inst, VkDebugUtilsMessengerEXT messenger,
+                                     const VkAllocationCallbacks *pAllocator);
+void util_DestroyDebugUtilsMessengers(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator,
+                                      uint32_t num_messengers, VkDebugUtilsMessengerEXT *messengers);
+void util_FreeDebugUtilsMessengerCreateInfos(const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerCreateInfoEXT *infos,
+                                             VkDebugUtilsMessengerEXT *messengers);
+
+// VK_EXT_debug_report related items
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugReportCallbackEXT(VkInstance instance,
+                                                                       const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
+                                                                       const VkAllocationCallbacks *pAllocator,
+                                                                       VkDebugReportCallbackEXT *pCallback);
+
+VKAPI_ATTR void VKAPI_CALL terminator_DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
+                                                                    const VkAllocationCallbacks *pAllocator);
+
+VKAPI_ATTR void VKAPI_CALL terminator_DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags,
+                                                            VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location,
+                                                            int32_t msgCode, const char *pLayerPrefix, const char *pMsg);
+
+VkResult util_CreateDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
+                                        const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT callback);
+VkResult util_CreateDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator,
+                                         uint32_t num_callbacks, VkDebugReportCallbackCreateInfoEXT *infos,
+                                         VkDebugReportCallbackEXT *callbacks);
+VkBool32 util_DebugReportMessage(const struct loader_instance *inst, VkFlags msgFlags, VkDebugReportObjectTypeEXT objectType,
+                                 uint64_t srcObject, size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg);
+VkResult util_CopyDebugReportCreateInfos(const void *pChain, const VkAllocationCallbacks *pAllocator, uint32_t *num_callbacks,
+                                         VkDebugReportCallbackCreateInfoEXT **infos, VkDebugReportCallbackEXT **callbacks);
+void util_DestroyDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackEXT callback,
+                                     const VkAllocationCallbacks *pAllocator);
+void util_DestroyDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator, uint32_t num_callbacks,
+                                      VkDebugReportCallbackEXT *callbacks);
+void util_FreeDebugReportCreateInfos(const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackCreateInfoEXT *infos,
+                                     VkDebugReportCallbackEXT *callbacks);
index 65c625ea2437697100fc8e61d0dc2dd719996574..2b70af709d5dda271123cd2c501a3d76dfa672fd 100644 (file)
@@ -28,7 +28,7 @@
 #include "vk_loader_extensions.h"
 #include <vulkan/vk_icd.h>
 #include "wsi.h"
-#include "debug_report.h"
+#include "debug_utils.h"
 
 // ---- Manually added trampoline/terminator functions
 
index 463e352bd538fca5ed3c9517e89cf679baeaf24b..1196edf57d7fb1411d809a895fa0384d19a8e542 100644 (file)
@@ -20,7 +20,7 @@
  */
 
 #include <string.h>
-#include "debug_report.h"
+#include "debug_utils.h"
 #include "wsi.h"
 
 static inline void *trampolineGetProcAddr(struct loader_instance *inst, const char *funcName) {
@@ -189,7 +189,7 @@ static inline void *trampolineGetProcAddr(struct loader_instance *inst, const ch
 
     // Instance extensions
     void *addr;
-    if (debug_report_instance_gpa(inst, funcName, &addr)) return addr;
+    if (debug_utils_InstanceGpa(inst, funcName, &addr)) return addr;
 
     if (wsi_swapchain_instance_gpa(inst, funcName, &addr)) return addr;
 
index d4e0e026c9dc55a0856e8cec362a3db98c657062..92be90b7fa7fae5a81fa88a7b5db503f6cd1b2f2 100644 (file)
@@ -45,7 +45,7 @@
 #include "vk_loader_platform.h"
 #include "loader.h"
 #include "gpa_helper.h"
-#include "debug_report.h"
+#include "debug_utils.h"
 #include "wsi.h"
 #include "vulkan/vk_icd.h"
 #include "cJSON.h"
@@ -322,8 +322,46 @@ void loader_log(const struct loader_instance *inst, VkFlags msg_type, int32_t ms
     va_end(ap);
 
     if (inst) {
-        util_DebugReportMessage(inst, msg_type, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, (uint64_t)(uintptr_t)inst, 0, msg_code,
-                                "loader", msg);
+        VkDebugUtilsMessageSeverityFlagBitsEXT severity;
+        VkDebugUtilsMessageTypeFlagsEXT type;
+        VkDebugUtilsMessengerCallbackDataEXT callback_data;
+        VkDebugUtilsObjectNameInfoEXT object_name;
+
+        if ((msg_type & LOADER_INFO_BIT) != 0) {
+            severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
+        } else if ((msg_type & LOADER_WARN_BIT) != 0) {
+            severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
+        } else if ((msg_type & LOADER_ERROR_BIT) != 0) {
+            severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
+        } else if ((msg_type & LOADER_DEBUG_BIT) != 0) {
+            severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
+        }
+
+        if ((msg_type & LOADER_PERF_BIT) != 0) {
+            type = VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
+        } else {
+            type = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
+        }
+
+        callback_data.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT;
+        callback_data.pNext = NULL;
+        callback_data.flags = 0;
+        callback_data.pMessageIdName = "Loader Message";
+        callback_data.messageIdNumber = 0;
+        callback_data.pMessage = msg;
+        callback_data.queueLabelCount = 0;
+        callback_data.pQueueLabels = NULL;
+        callback_data.cmdBufLabelCount = 0;
+        callback_data.pCmdBufLabels = NULL;
+        callback_data.objectCount = 1;
+        callback_data.pObjects = &object_name;
+        object_name.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
+        object_name.pNext = NULL;
+        object_name.objectType = VK_OBJECT_TYPE_INSTANCE;
+        object_name.objectHandle = (uint64_t)(uintptr_t)inst;
+        object_name.pObjectName = NULL;
+
+        util_SubmitDebugUtilsMessageEXT(inst, severity, type, &callback_data);
     }
 
     if (!(msg_type & g_loader_log_msgs)) {
@@ -1608,7 +1646,7 @@ VkResult loader_get_icd_loader_instance_extensions(const struct loader_instance
     };
 
     // Traverse loader's extensions, adding non-duplicate extensions to the list
-    debug_report_add_instance_extensions(inst, inst_exts);
+    debug_utils_AddInstanceExtensions(inst, inst_exts);
 
 out:
     return res;
index ae928f9558a5d10dccde1e66a4de25a1803fcc4f..9342e21cf5fdc58ab034fee9ee4bcaeca967c093 100644 (file)
@@ -276,9 +276,12 @@ struct loader_instance {
     union loader_instance_extension_enables enabled_known_extensions;
 
     VkLayerDbgFunctionNode *DbgFunctionHead;
-    uint32_t num_tmp_callbacks;
-    VkDebugReportCallbackCreateInfoEXT *tmp_dbg_create_infos;
-    VkDebugReportCallbackEXT *tmp_callbacks;
+    uint32_t num_tmp_report_callbacks;
+    VkDebugReportCallbackCreateInfoEXT *tmp_report_create_infos;
+    VkDebugReportCallbackEXT *tmp_report_callbacks;
+    uint32_t num_tmp_messengers;
+    VkDebugUtilsMessengerCreateInfoEXT *tmp_messenger_create_infos;
+    VkDebugUtilsMessengerEXT *tmp_messengers;
 
     VkAllocationCallbacks alloc_callbacks;
 
index 7915006d0d898528c7a7acde193fadf79c026a1c..6b0464d44b26a4898dd2128c25dd2544f3d709f6 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "vk_loader_platform.h"
 #include "loader.h"
-#include "debug_report.h"
+#include "debug_utils.h"
 #include "wsi.h"
 #include "vk_loader_extensions.h"
 #include "gpa_helper.h"
@@ -324,23 +324,42 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCr
         ptr_instance->app_api_minor_version = VK_VERSION_MINOR(pCreateInfo->pApplicationInfo->apiVersion);
     }
 
-    // Look for one or more debug report create info structures
+    // Look for one or more VK_EXT_debug_report or VK_EXT_debug_utils create info structures
     // and setup a callback(s) for each one found.
-    ptr_instance->num_tmp_callbacks = 0;
-    ptr_instance->tmp_dbg_create_infos = NULL;
-    ptr_instance->tmp_callbacks = NULL;
-    if (util_CopyDebugReportCreateInfos(pCreateInfo->pNext, pAllocator, &ptr_instance->num_tmp_callbacks,
-                                        &ptr_instance->tmp_dbg_create_infos, &ptr_instance->tmp_callbacks)) {
-        // One or more were found, but allocation failed.  Therefore, clean up
-        // and fail this function:
+    ptr_instance->num_tmp_report_callbacks = 0;
+    ptr_instance->tmp_report_create_infos = NULL;
+    ptr_instance->tmp_report_callbacks = NULL;
+    ptr_instance->num_tmp_messengers = 0;
+    ptr_instance->tmp_messenger_create_infos = NULL;
+    ptr_instance->tmp_messengers = NULL;
+
+    // Handle cases of VK_EXT_debug_utils
+    if (util_CopyDebugUtilsMessengerCreateInfos(pCreateInfo->pNext, pAllocator, &ptr_instance->num_tmp_messengers,
+                                                &ptr_instance->tmp_messenger_create_infos, &ptr_instance->tmp_messengers)) {
+        // One or more were found, but allocation failed.  Therefore, clean up and fail this function:
         res = VK_ERROR_OUT_OF_HOST_MEMORY;
         goto out;
-    } else if (ptr_instance->num_tmp_callbacks > 0) {
+    } else if (ptr_instance->num_tmp_messengers > 0) {
+        // Setup the temporary messenger(s) here to catch early issues:
+        if (util_CreateDebugUtilsMessengers(ptr_instance, pAllocator, ptr_instance->num_tmp_messengers,
+                                            ptr_instance->tmp_messenger_create_infos, ptr_instance->tmp_messengers)) {
+            // Failure of setting up one or more of the messenger.  Therefore, clean up and fail this function:
+            res = VK_ERROR_OUT_OF_HOST_MEMORY;
+            goto out;
+        }
+    }
+
+    // Handle cases of VK_EXT_debug_report
+    if (util_CopyDebugReportCreateInfos(pCreateInfo->pNext, pAllocator, &ptr_instance->num_tmp_report_callbacks,
+                                        &ptr_instance->tmp_report_create_infos, &ptr_instance->tmp_report_callbacks)) {
+        // One or more were found, but allocation failed.  Therefore, clean up and fail this function:
+        res = VK_ERROR_OUT_OF_HOST_MEMORY;
+        goto out;
+    } else if (ptr_instance->num_tmp_report_callbacks > 0) {
         // Setup the temporary callback(s) here to catch early issues:
-        if (util_CreateDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_callbacks,
-                                            ptr_instance->tmp_dbg_create_infos, ptr_instance->tmp_callbacks)) {
-            // Failure of setting up one or more of the callback.  Therefore,
-            // clean up and fail this function:
+        if (util_CreateDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_report_callbacks,
+                                            ptr_instance->tmp_report_create_infos, ptr_instance->tmp_report_callbacks)) {
+            // Failure of setting up one or more of the callback.  Therefore, clean up and fail this function:
             res = VK_ERROR_OUT_OF_HOST_MEMORY;
             goto out;
         }
@@ -404,7 +423,7 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCr
         memset(ptr_instance->enabled_known_extensions.padding, 0, sizeof(uint64_t) * 4);
 
         wsi_create_instance(ptr_instance, &ici);
-        debug_report_create_instance(ptr_instance, &ici);
+        debug_utils_CreateInstance(ptr_instance, &ici);
         extensions_create_instance(ptr_instance, &ici);
 
         *pInstance = created_instance;
@@ -426,10 +445,19 @@ out:
             if (NULL != ptr_instance->disp) {
                 loader_instance_heap_free(ptr_instance, ptr_instance->disp);
             }
-            if (ptr_instance->num_tmp_callbacks > 0) {
-                util_DestroyDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_callbacks,
-                                                 ptr_instance->tmp_callbacks);
-                util_FreeDebugReportCreateInfos(pAllocator, ptr_instance->tmp_dbg_create_infos, ptr_instance->tmp_callbacks);
+            if (ptr_instance->num_tmp_report_callbacks > 0) {
+                // Remove temporary VK_EXT_debug_report items
+                util_DestroyDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_report_callbacks,
+                                                 ptr_instance->tmp_report_callbacks);
+                util_FreeDebugReportCreateInfos(pAllocator, ptr_instance->tmp_report_create_infos,
+                                                ptr_instance->tmp_report_callbacks);
+            }
+            if (ptr_instance->num_tmp_messengers > 0) {
+                // Remove temporary VK_EXT_debug_utils items
+                util_DestroyDebugUtilsMessengers(ptr_instance, pAllocator, ptr_instance->num_tmp_messengers,
+                                                 ptr_instance->tmp_messengers);
+                util_FreeDebugUtilsMessengerCreateInfos(pAllocator, ptr_instance->tmp_messenger_create_infos,
+                                                        ptr_instance->tmp_messengers);
             }
 
             if (NULL != ptr_instance->expanded_activated_layer_list.list) {
@@ -445,9 +473,11 @@ out:
 
             loader_instance_heap_free(ptr_instance, ptr_instance);
         } else {
-            // Remove temporary debug_report callback
-            util_DestroyDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_callbacks,
-                                             ptr_instance->tmp_callbacks);
+            // Remove temporary VK_EXT_debug_report or VK_EXT_debug_utils items
+            util_DestroyDebugUtilsMessengers(ptr_instance, pAllocator, ptr_instance->num_tmp_messengers,
+                                             ptr_instance->tmp_messengers);
+            util_DestroyDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_report_callbacks,
+                                             ptr_instance->tmp_report_callbacks);
         }
 
         if (loaderLocked) {
@@ -462,6 +492,7 @@ LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance,
     const VkLayerInstanceDispatchTable *disp;
     struct loader_instance *ptr_instance = NULL;
     bool callback_setup = false;
+    bool messenger_setup = false;
 
     if (instance == VK_NULL_HANDLE) {
         return;
@@ -477,10 +508,18 @@ LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance,
         ptr_instance->alloc_callbacks = *pAllocator;
     }
 
-    if (ptr_instance->num_tmp_callbacks > 0) {
-        // Setup the temporary callback(s) here to catch cleanup issues:
-        if (!util_CreateDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_callbacks,
-                                             ptr_instance->tmp_dbg_create_infos, ptr_instance->tmp_callbacks)) {
+    if (ptr_instance->num_tmp_messengers > 0) {
+        // Setup the temporary VK_EXT_debug_utils messenger(s) here to catch cleanup issues:
+        if (!util_CreateDebugUtilsMessengers(ptr_instance, pAllocator, ptr_instance->num_tmp_messengers,
+                                             ptr_instance->tmp_messenger_create_infos, ptr_instance->tmp_messengers)) {
+            messenger_setup = true;
+        }
+    }
+
+    if (ptr_instance->num_tmp_report_callbacks > 0) {
+        // Setup the temporary VK_EXT_debug_report callback(s) here to catch cleanup issues:
+        if (!util_CreateDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_report_callbacks,
+                                             ptr_instance->tmp_report_create_infos, ptr_instance->tmp_report_callbacks)) {
             callback_setup = true;
         }
     }
@@ -508,9 +547,15 @@ LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance,
         loader_instance_heap_free(ptr_instance, ptr_instance->phys_dev_groups_tramp);
     }
 
+    if (messenger_setup) {
+        util_DestroyDebugUtilsMessengers(ptr_instance, pAllocator, ptr_instance->num_tmp_messengers, ptr_instance->tmp_messengers);
+        util_FreeDebugUtilsMessengerCreateInfos(pAllocator, ptr_instance->tmp_messenger_create_infos, ptr_instance->tmp_messengers);
+    }
+
     if (callback_setup) {
-        util_DestroyDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_callbacks, ptr_instance->tmp_callbacks);
-        util_FreeDebugReportCreateInfos(pAllocator, ptr_instance->tmp_dbg_create_infos, ptr_instance->tmp_callbacks);
+        util_DestroyDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_report_callbacks,
+                                         ptr_instance->tmp_report_callbacks);
+        util_FreeDebugReportCreateInfos(pAllocator, ptr_instance->tmp_report_create_infos, ptr_instance->tmp_report_callbacks);
     }
     loader_instance_heap_free(ptr_instance, ptr_instance->disp);
     loader_instance_heap_free(ptr_instance, ptr_instance);
index 425154d82632bf5f35b74b97d9bbcb2fd3bc7733..dfcf5b2a4618a7a2d52cd79abaa68d63c7b2510c 100644 (file)
 */
 #pragma once
 
-// Linked list node for tree of debug callback functions
-typedef struct VkLayerDbgFunctionNode_ {
+// Linked list node for tree of debug callbacks
+typedef struct VkDebugReportContent {
     VkDebugReportCallbackEXT msgCallback;
     PFN_vkDebugReportCallbackEXT pfnMsgCallback;
     VkFlags msgFlags;
+} VkDebugReportContent;
+
+typedef struct VkDebugUtilsMessengerContent {
+    VkDebugUtilsMessengerEXT messenger;
+    VkDebugUtilsMessageSeverityFlagsEXT messageSeverity;
+    VkDebugUtilsMessageTypeFlagsEXT messageType;
+    PFN_vkDebugUtilsMessengerCallbackEXT pfnUserCallback;
+} VkDebugUtilsMessengerContent;
+
+typedef struct VkLayerDbgFunctionNode_ {
+    bool is_messenger;
+    union {
+        VkDebugReportContent report;
+        VkDebugUtilsMessengerContent messenger;
+    };
     void *pUserData;
     struct VkLayerDbgFunctionNode_ *pNext;
 } VkLayerDbgFunctionNode;
index fb519b67639c12aa55abafa43191fec61c0bafd9..e460f9642dfe87be9c260efdfc83d3262194d513 100644 (file)
@@ -747,7 +747,8 @@ class HelperFileOutputGenerator(OutputGenerator):
     #
     # Object types header: create object enum type header file
     def GenerateObjectTypesHeader(self):
-        object_types_header = '// Object Type enum for validation layer internal object handling\n'
+        object_types_header = ''
+        object_types_header += '// Object Type enum for validation layer internal object handling\n'
         object_types_header += 'typedef enum VulkanObjectType {\n'
         object_types_header += '    kVulkanObjectTypeUnknown = 0,\n'
         enum_num = 1
@@ -777,7 +778,7 @@ class HelperFileOutputGenerator(OutputGenerator):
         object_types_header += '\n'
         object_types_header += '// Helper array to get Vulkan VK_EXT_debug_report object type enum from the internal layers version\n'
         object_types_header += 'const VkDebugReportObjectTypeEXT get_debug_report_enum[] = {\n'
-        object_types_header += '    VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, // No Match\n'
+        object_types_header += '    VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, // kVulkanObjectTypeUnknown\n'
         for object_type in type_list:
             search_type = object_type.replace("kVulkanObjectType", "").lower()
             for vk_object_type in self.debug_report_object_types:
@@ -793,7 +794,7 @@ class HelperFileOutputGenerator(OutputGenerator):
         object_types_header += '\n'
         object_types_header += '// Helper array to get Official Vulkan VkObjectType enum from the internal layers version\n'
         object_types_header += 'const VkObjectType get_object_type_enum[] = {\n'
-        object_types_header += '    VK_OBJECT_TYPE_UNKNOWN, // No Match\n'
+        object_types_header += '    VK_OBJECT_TYPE_UNKNOWN, // kVulkanObjectTypeUnknown\n'
         for object_type in type_list:
             search_type = object_type.replace("kVulkanObjectType", "").lower()
             for vk_object_type in self.core_object_types:
@@ -804,6 +805,47 @@ class HelperFileOutputGenerator(OutputGenerator):
                     break
         object_types_header += '};\n'
 
+        # Create a function to convert from VkDebugReportObjectTypeEXT to VkObjectType
+        object_types_header += '\n'
+        object_types_header += '// Helper function to convert from VkDebugReportObjectTypeEXT to VkObjectType\n'
+        object_types_header += 'static VkObjectType convertDebugReportObjectToCoreObject(VkDebugReportObjectTypeEXT debug_report_obj){\n'
+        object_types_header += '    if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT) {\n'
+        object_types_header += '        return VK_OBJECT_TYPE_UNKNOWN;\n'
+        for core_object_type in self.core_object_types:
+            core_target_type = core_object_type.replace("VK_OBJECT_TYPE_", "").lower()
+            core_target_type = core_target_type.replace("_", "")
+            for dr_object_type in self.debug_report_object_types:
+                dr_target_type = dr_object_type.replace("VK_DEBUG_REPORT_OBJECT_TYPE_", "").lower()
+                dr_target_type = dr_target_type[:-4]
+                dr_target_type = dr_target_type.replace("_", "")
+                if core_target_type == dr_target_type:
+                    object_types_header += '    } else if (debug_report_obj == %s) {\n' % dr_object_type
+                    object_types_header += '        return %s;\n' % core_object_type
+                    break
+        object_types_header += '    }\n'
+        object_types_header += '    return VK_OBJECT_TYPE_UNKNOWN;\n'
+        object_types_header += '}\n'
+
+        # Create a function to convert from VkObjectType to VkDebugReportObjectTypeEXT
+        object_types_header += '\n'
+        object_types_header += '// Helper function to convert from VkDebugReportObjectTypeEXT to VkObjectType\n'
+        object_types_header += 'static VkDebugReportObjectTypeEXT convertCoreObjectToDebugReportObject(VkObjectType core_report_obj){\n'
+        object_types_header += '    if (core_report_obj == VK_OBJECT_TYPE_UNKNOWN) {\n'
+        object_types_header += '        return VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT;\n'
+        for core_object_type in self.core_object_types:
+            core_target_type = core_object_type.replace("VK_OBJECT_TYPE_", "").lower()
+            core_target_type = core_target_type.replace("_", "")
+            for dr_object_type in self.debug_report_object_types:
+                dr_target_type = dr_object_type.replace("VK_DEBUG_REPORT_OBJECT_TYPE_", "").lower()
+                dr_target_type = dr_target_type[:-4]
+                dr_target_type = dr_target_type.replace("_", "")
+                if core_target_type == dr_target_type:
+                    object_types_header += '    } else if (core_report_obj == %s) {\n' % core_object_type
+                    object_types_header += '        return %s;\n' % dr_object_type
+                    break
+        object_types_header += '    }\n'
+        object_types_header += '    return VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT;\n'
+        object_types_header += '}\n'
         return object_types_header
     #
     # Determine if a structure needs a safe_struct helper function
index a4a3f8fbbf175b59126b346f81f4b6e2e8d8a41d..ae2b3dac74c242dda50de4a624d345c237dda883 100644 (file)
@@ -40,14 +40,25 @@ WSI_EXT_NAMES = ['VK_KHR_surface',
                  'VK_KHR_swapchain',
                  'VK_KHR_display_swapchain']
 
+ADD_INST_CMDS = ['vkCreateInstance',
+                 'vkEnumerateInstanceExtensionProperties',
+                 'vkEnumerateInstanceLayerProperties',
+                 'vkEnumerateInstanceVersion']
+
 AVOID_EXT_NAMES = ['VK_EXT_debug_report']
 
+AVOID_CMD_NAMES = ['vkCreateDebugUtilsMessengerEXT',
+                   'vkDestroyDebugUtilsMessengerEXT',
+                   'vkSubmitDebugUtilsMessageEXT']
+
 DEVICE_CMDS_NEED_TERM = ['vkGetDeviceProcAddr',
                          'vkCreateSwapchainKHR',
                          'vkCreateSharedSwapchainsKHR',
                          'vkGetDeviceGroupSurfacePresentModesKHR',
                          'vkDebugMarkerSetObjectTagEXT',
-                         'vkDebugMarkerSetObjectNameEXT']
+                         'vkDebugMarkerSetObjectNameEXT',
+                         'vkSetDebugUtilsObjectNameEXT',
+                         'vkSetDebugUtilsObjectTagEXT']
                          
 ALIASED_CMDS = {
     'vkEnumeratePhysicalDeviceGroupsKHR':                   'vkEnumeratePhysicalDeviceGroups',
@@ -176,7 +187,7 @@ class LoaderExtensionOutputGenerator(OutputGenerator):
             preamble += '#include "vk_loader_extensions.h"\n'
             preamble += '#include <vulkan/vk_icd.h>\n'
             preamble += '#include "wsi.h"\n'
-            preamble += '#include "debug_report.h"\n'
+            preamble += '#include "debug_utils.h"\n'
             preamble += '#include "extension_manual.h"\n'
 
         elif self.genOpts.filename == 'vk_layer_dispatch_table.h':
@@ -467,7 +478,9 @@ class LoaderExtensionOutputGenerator(OutputGenerator):
                 commands = self.ext_commands
 
             for cur_cmd in commands:
-                if cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice':
+                is_inst_handle_type = cur_cmd.name in ADD_INST_CMDS or cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice'
+                if is_inst_handle_type:
+
                     if cur_cmd.ext_name != cur_extension_name:
                         if 'VK_VERSION_' in cur_cmd.ext_name:
                             table += '\n    // ---- Core %s commands\n' % cur_cmd.ext_name[11:]
@@ -506,7 +519,9 @@ class LoaderExtensionOutputGenerator(OutputGenerator):
                 commands = self.ext_commands
 
             for cur_cmd in commands:
-                if cur_cmd.handle_type != 'VkInstance' and cur_cmd.handle_type != 'VkPhysicalDevice':
+                is_inst_handle_type = cur_cmd.name in ADD_INST_CMDS or cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice'
+                if not is_inst_handle_type:
+
                     if cur_cmd.ext_name != cur_extension_name:
                         if 'VK_VERSION_' in cur_cmd.ext_name:
                             table += '\n    // ---- Core %s commands\n' % cur_cmd.ext_name[11:]
@@ -545,7 +560,7 @@ class LoaderExtensionOutputGenerator(OutputGenerator):
                 commands = self.ext_commands
 
             for cur_cmd in commands:
-                is_inst_handle_type = cur_cmd.ext_type == 'instance' or cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice'
+                is_inst_handle_type = cur_cmd.name in ADD_INST_CMDS or cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice'
                 if ((is_inst_handle_type or cur_cmd.name in DEVICE_CMDS_NEED_TERM) and
                     (cur_cmd.name != 'vkGetInstanceProcAddr' and cur_cmd.name != 'vkEnumerateDeviceLayerProperties')):
 
@@ -607,7 +622,7 @@ class LoaderExtensionOutputGenerator(OutputGenerator):
 
             required = False
             for cur_cmd in commands:
-                is_inst_handle_type = cur_cmd.ext_type == 'instance' or cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice'
+                is_inst_handle_type = cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice'
                 if ((is_inst_handle_type or cur_cmd.name in DEVICE_CMDS_NEED_TERM) and (cur_cmd.name not in skip_gipa_commands)):
 
                     if cur_cmd.ext_name != cur_extension_name:
@@ -666,7 +681,7 @@ class LoaderExtensionOutputGenerator(OutputGenerator):
         terminators += '// Loader core instance terminators\n'
 
         for cur_cmd in self.core_commands:
-            is_inst_handle_type = cur_cmd.ext_type == 'instance' or cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice'
+            is_inst_handle_type = cur_cmd.name in ADD_INST_CMDS or cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice'
             if is_inst_handle_type:
                 mod_string = ''
                 new_terminator = cur_cmd.cdecl
@@ -878,6 +893,7 @@ class LoaderExtensionOutputGenerator(OutputGenerator):
         for ext_cmd in self.ext_commands:
             if (ext_cmd.ext_name in WSI_EXT_NAMES or
                 ext_cmd.ext_name in AVOID_EXT_NAMES or
+                ext_cmd.name in AVOID_CMD_NAMES or
                 ext_cmd.name in manual_ext_commands):
                 continue
 
@@ -937,8 +953,9 @@ class LoaderExtensionOutputGenerator(OutputGenerator):
                 return_prefix += 'return '
                 has_return_type = True
 
-            if (ext_cmd.ext_type == 'instance' or ext_cmd.handle_type == 'VkPhysicalDevice' or
-                'DebugMarkerSetObject' in ext_cmd.name or ext_cmd.name in DEVICE_CMDS_NEED_TERM):
+            if (ext_cmd.handle_type == 'VkInstance' or ext_cmd.handle_type == 'VkPhysicalDevice' or
+                'DebugMarkerSetObject' in ext_cmd.name or 'SetDebugUtilsObject' in ext_cmd.name or
+                ext_cmd.name in DEVICE_CMDS_NEED_TERM):
                 requires_terminator = 1
 
             if requires_terminator == 1:
@@ -973,6 +990,22 @@ class LoaderExtensionOutputGenerator(OutputGenerator):
                     funcs += '        struct loader_physical_device_tramp *phys_dev_tramp = (struct loader_physical_device_tramp *)(uintptr_t)pTagInfo->object;\n'
                     funcs += '        local_tag_info.object = (uint64_t)(uintptr_t)phys_dev_tramp->phys_dev;\n'
                     funcs += '    }\n'
+                elif 'SetDebugUtilsObjectName' in ext_cmd.name:
+                    funcs += '    VkDebugUtilsObjectNameInfoEXT local_name_info;\n'
+                    funcs += '    memcpy(&local_name_info, pNameInfo, sizeof(VkDebugUtilsObjectNameInfoEXT));\n'
+                    funcs += '    // If this is a physical device, we have to replace it with the proper one for the next call.\n'
+                    funcs += '    if (pNameInfo->objectType == VK_OBJECT_TYPE_PHYSICAL_DEVICE) {\n'
+                    funcs += '        struct loader_physical_device_tramp *phys_dev_tramp = (struct loader_physical_device_tramp *)(uintptr_t)pNameInfo->objectHandle;\n'
+                    funcs += '        local_name_info.objectHandle = (uint64_t)(uintptr_t)phys_dev_tramp->phys_dev;\n'
+                    funcs += '    }\n'
+                elif 'SetDebugUtilsObjectTag' in ext_cmd.name:
+                    funcs += '    VkDebugUtilsObjectTagInfoEXT local_tag_info;\n'
+                    funcs += '    memcpy(&local_tag_info, pTagInfo, sizeof(VkDebugUtilsObjectTagInfoEXT));\n'
+                    funcs += '    // If this is a physical device, we have to replace it with the proper one for the next call.\n'
+                    funcs += '    if (pTagInfo->objectType == VK_OBJECT_TYPE_PHYSICAL_DEVICE) {\n'
+                    funcs += '        struct loader_physical_device_tramp *phys_dev_tramp = (struct loader_physical_device_tramp *)(uintptr_t)pTagInfo->objectHandle;\n'
+                    funcs += '        local_tag_info.objectHandle = (uint64_t)(uintptr_t)phys_dev_tramp->phys_dev;\n'
+                    funcs += '    }\n'
 
                 funcs += return_prefix
                 funcs += 'disp->'
@@ -985,9 +1018,9 @@ class LoaderExtensionOutputGenerator(OutputGenerator):
 
                     if param.type == 'VkPhysicalDevice':
                         funcs += 'unwrapped_phys_dev'
-                    elif 'DebugMarkerSetObject' in ext_cmd.name and param.name == 'pNameInfo':
+                    elif ('DebugMarkerSetObject' in ext_cmd.name or 'SetDebugUtilsObject' in ext_cmd.name) and param.name == 'pNameInfo':
                             funcs += '&local_name_info'
-                    elif 'DebugMarkerSetObject' in ext_cmd.name and param.name == 'pTagInfo':
+                    elif ('DebugMarkerSetObject' in ext_cmd.name or 'SetDebugUtilsObject' in ext_cmd.name) and param.name == 'pTagInfo':
                             funcs += '&local_tag_info'
                     else:
                         funcs += param.name
@@ -1059,7 +1092,7 @@ class LoaderExtensionOutputGenerator(OutputGenerator):
                         count += 1
                     funcs += ');\n'
 
-                elif has_surface == 1 and ext_cmd.ext_type == 'device':
+                elif has_surface == 1 and not (ext_cmd.handle_type == 'VkPhysicalDevice' or ext_cmd.handle_type == 'VkInstance'):
                     funcs += '    uint32_t icd_index = 0;\n'
                     funcs += '    struct loader_device *dev;\n'
                     funcs += '    struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, &icd_index);\n'
@@ -1096,7 +1129,7 @@ class LoaderExtensionOutputGenerator(OutputGenerator):
 
                 elif ext_cmd.handle_type == 'VkInstance':
                     funcs += '#error("Not implemented. Likely needs to be manually generated!");\n'
-                elif 'DebugMarkerSetObject' in ext_cmd.name:
+                elif 'DebugMarkerSetObject' in ext_cmd.name or 'SetDebugUtilsObject' in ext_cmd.name:
                     funcs += '    uint32_t icd_index = 0;\n'
                     funcs += '    struct loader_device *dev;\n'
                     funcs += '    struct loader_icd_term *icd_term = loader_get_icd_and_device(%s, &dev, &icd_index);\n' % (ext_cmd.params[0].name)
@@ -1131,6 +1164,45 @@ class LoaderExtensionOutputGenerator(OutputGenerator):
                         funcs += '                if (NULL != icd_surface->real_icd_surfaces) {\n'
                         funcs += '                    local_tag_info.object = (uint64_t)icd_surface->real_icd_surfaces[icd_index];\n'
                         funcs += '                }\n'
+                    elif 'SetDebugUtilsObjectName' in ext_cmd.name:
+                        funcs += '        VkDebugUtilsObjectNameInfoEXT local_name_info;\n'
+                        funcs += '        memcpy(&local_name_info, pNameInfo, sizeof(VkDebugUtilsObjectNameInfoEXT));\n'
+                        funcs += '        // If this is a physical device, we have to replace it with the proper one for the next call.\n'
+                        funcs += '        if (pNameInfo->objectType == VK_OBJECT_TYPE_PHYSICAL_DEVICE) {\n'
+                        funcs += '            struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)(uintptr_t)pNameInfo->objectHandle;\n'
+                        funcs += '            local_name_info.objectHandle = (uint64_t)(uintptr_t)phys_dev_term->phys_dev;\n'
+                        funcs += '        // If this is a KHR_surface, and the ICD has created its own, we have to replace it with the proper one for the next call.\n'
+                        funcs += '        } else if (pNameInfo->objectType == VK_OBJECT_TYPE_SURFACE_KHR) {\n'
+                        funcs += '            if (NULL != icd_term && NULL != icd_term->dispatch.CreateSwapchainKHR) {\n'
+                        funcs += '                VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pNameInfo->objectHandle;\n'
+                        funcs += '                if (NULL != icd_surface->real_icd_surfaces) {\n'
+                        funcs += '                    local_name_info.objectHandle = (uint64_t)icd_surface->real_icd_surfaces[icd_index];\n'
+                        funcs += '                }\n'
+                    elif 'SetDebugUtilsObjectTag' in ext_cmd.name:
+                        funcs += '        VkDebugUtilsObjectTagInfoEXT local_tag_info;\n'
+                        funcs += '        memcpy(&local_tag_info, pTagInfo, sizeof(VkDebugUtilsObjectTagInfoEXT));\n'
+                        funcs += '        // If this is a physical device, we have to replace it with the proper one for the next call.\n'
+                        funcs += '        if (pTagInfo->objectType == VK_OBJECT_TYPE_PHYSICAL_DEVICE) {\n'
+                        funcs += '            struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)(uintptr_t)pTagInfo->objectHandle;\n'
+                        funcs += '            local_tag_info.objectHandle = (uint64_t)(uintptr_t)phys_dev_term->phys_dev;\n'
+                        funcs += '        // If this is a KHR_surface, and the ICD has created its own, we have to replace it with the proper one for the next call.\n'
+                        funcs += '        } else if (pTagInfo->objectType == VK_OBJECT_TYPE_SURFACE_KHR) {\n'
+                        funcs += '            if (NULL != icd_term && NULL != icd_term->dispatch.CreateSwapchainKHR) {\n'
+                        funcs += '                VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pTagInfo->objectHandle;\n'
+                        funcs += '                if (NULL != icd_surface->real_icd_surfaces) {\n'
+                        funcs += '                    local_tag_info.objectHandle = (uint64_t)icd_surface->real_icd_surfaces[icd_index];\n'
+                        funcs += '                }\n'
+                    else:
+                        funcs += '        if (%s->objectType == VK_OBJECT_TYPE_PHYSICAL_DEVICE) {\n' % (ext_cmd.params[1].name)
+                        funcs += '            struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)(uintptr_t)%s->objectHandle;\n' % (ext_cmd.params[1].name)
+                        funcs += '            %s->objectHandle = (uint64_t)(uintptr_t)phys_dev_term->phys_dev;\n' % (ext_cmd.params[1].name)
+                        funcs += '        // If this is a KHR_surface, and the ICD has created its own, we have to replace it with the proper one for the next call.\n'
+                        funcs += '        } else if (%s->objectType == VK_OBJECT_TYPE_SURFACE_KHR) {\n' % (ext_cmd.params[1].name)
+                        funcs += '            if (NULL != icd_term && NULL != icd_term->dispatch.CreateSwapchainKHR) {\n'
+                        funcs += '                VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)%s->objectHandle;\n' % (ext_cmd.params[1].name)
+                        funcs += '                if (NULL != icd_surface->real_icd_surfaces) {\n'
+                        funcs += '                    %s->objectHandle = (uint64_t)icd_surface->real_icd_surfaces[icd_index];\n' % (ext_cmd.params[1].name)
+                        funcs += '                }\n'
                     funcs += '            }\n'
                     funcs += '        }\n'
                     funcs += '        return icd_term->dispatch.'
@@ -1145,9 +1217,9 @@ class LoaderExtensionOutputGenerator(OutputGenerator):
                             funcs += 'phys_dev_term->phys_dev'
                         elif param.type == 'VkSurfaceKHR':
                             funcs += 'icd_surface->real_icd_surfaces[icd_index]'
-                        elif 'DebugMarkerSetObject' in ext_cmd.name and param.name == 'pNameInfo':
+                        elif ('DebugMarkerSetObject' in ext_cmd.name or 'SetDebugUtilsObject' in ext_cmd.name) and param.name == 'pNameInfo':
                             funcs += '&local_name_info'
-                        elif 'DebugMarkerSetObject' in ext_cmd.name and param.name == 'pTagInfo':
+                        elif ('DebugMarkerSetObject' in ext_cmd.name or 'SetDebugUtilsObject' in ext_cmd.name) and param.name == 'pTagInfo':
                             funcs += '&local_tag_info'
                         else:
                             funcs += param.name
@@ -1202,7 +1274,8 @@ class LoaderExtensionOutputGenerator(OutputGenerator):
         for cur_cmd in self.ext_commands:
             if ('VK_VERSION_' in cur_cmd.ext_name or
                 cur_cmd.ext_name in WSI_EXT_NAMES or
-                cur_cmd.ext_name in AVOID_EXT_NAMES):
+                cur_cmd.ext_name in AVOID_EXT_NAMES or
+                cur_cmd.name in AVOID_CMD_NAMES ):
                 continue
 
             if cur_cmd.ext_name != cur_extension_name:
@@ -1252,8 +1325,8 @@ class LoaderExtensionOutputGenerator(OutputGenerator):
         create_func += '    for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {\n'
         for ext in entries:
             if ('VK_VERSION_' in ext.name or ext.name in WSI_EXT_NAMES or
-                ext.name in AVOID_EXT_NAMES or ext.type == 'device' or
-                ext.num_commands == 0):
+                ext.name in AVOID_EXT_NAMES or ext.name in AVOID_CMD_NAMES or
+                ext.type == 'device' or ext.num_commands == 0):
                 continue
 
             if ext.name != cur_extension_name:
index 405a5b7cdf41e0659c6eba9ba2a796f23f3ab830..26c1105af1d62a1b4b16a46f550bd3b967f755fd 100644 (file)
@@ -172,6 +172,17 @@ class ObjectTrackerOutputGenerator(OutputGenerator):
             'vkGetDeviceQueue',
             'vkGetSwapchainImagesKHR',
             'vkCreateDescriptorSetLayout',
+            'vkCreateDebugUtilsMessengerEXT',
+            'vkDestroyDebugUtilsMessengerEXT',
+            'vkSubmitDebugUtilsMessageEXT',
+            'vkSetDebugUtilsObjectNameEXT',
+            'vkSetDebugUtilsObjectTagEXT',
+            'vkQueueBeginDebugUtilsLabelEXT',
+            'vkQueueEndDebugUtilsLabelEXT',
+            'vkQueueInsertDebugUtilsLabelEXT',
+            'vkCmdBeginDebugUtilsLabelEXT',
+            'vkCmdEndDebugUtilsLabelEXT',
+            'vkCmdInsertDebugUtilsLabelEXT',
             ]
         # These VUIDS are not implicit, but are best handled in this layer. Codegen for vkDestroy calls will generate a key
         # which is translated here into a good VU.  Saves ~40 checks.
index edd49b5568f4a38ecbf454338c60fe1807f6983f..4246eeae0312e49c3cf651cd181914beac0db111 100644 (file)
@@ -127,17 +127,12 @@ class ParameterValidationOutputGenerator(OutputGenerator):
         self.blacklist = [
             'vkGetInstanceProcAddr',
             'vkGetDeviceProcAddr',
-            'vkEnumerateInstanceLayerProperties',
-            'vkEnumerateInstanceExtensionsProperties',
-            'vkEnumerateDeviceLayerProperties',
-            'vkEnumerateDeviceExtensionsProperties',
-            'vkCreateDebugReportCallbackKHR',
-            'vkDestroyDebugReportCallbackKHR',
+            'vkEnumerateInstanceVersion',
             'vkEnumerateInstanceLayerProperties',
             'vkEnumerateInstanceExtensionProperties',
             'vkEnumerateDeviceLayerProperties',
-            'vkCmdDebugMarkerEndEXT',
             'vkEnumerateDeviceExtensionProperties',
+            'vkCmdDebugMarkerEndEXT',
             ]
         self.validate_only = [
             'vkCreateInstance',
@@ -150,6 +145,8 @@ class ParameterValidationOutputGenerator(OutputGenerator):
             'vkCreateCommandPool',
             'vkCreateRenderPass',
             'vkDestroyRenderPass',
+            'vkCreateDebugUtilsMessengerEXT',
+            'vkDestroyDebugUtilsMessengerEXT',
             ]
         # Structure fields to ignore
         self.structMemberBlacklist = { 'VkWriteDescriptorSet' : ['dstSet'] }
index fd88909cf7217f4d3948efdc6cd8bb3f9a6ae1b6..4ac65d671459bd3123da88eb6f83f2deeb41856f 100644 (file)
@@ -384,6 +384,8 @@ class ThreadOutputGenerator(OutputGenerator):
             'vkEnumerateInstanceExtensionProperties',
             'vkEnumerateDeviceLayerProperties',
             'vkEnumerateDeviceExtensionProperties',
+            'vkCreateDebugUtilsMessengerEXT',
+            'vkDestroyDebugUtilsMessengerEXT',
         ]
         if name in special_functions:
             decls = self.makeCDecls(cmdinfo.elem)
@@ -392,7 +394,7 @@ class ThreadOutputGenerator(OutputGenerator):
             self.appendSection('command', decls[0])
             self.intercepts += [ '    {"%s", (void*)%s},' % (name,name[2:]) ]
             return
-        if "QueuePresentKHR" in name or ("DebugMarker" in name and "EXT" in name):
+        if "QueuePresentKHR" in name or (("DebugMarker" in name or "DebugUtilsObject" in name) and "EXT" in name):
             self.appendSection('command', '// TODO - not wrapping EXT function ' + name)
             return
         # Determine first if this function needs to be intercepted
index 78526a3eae44e9aaf6a8d99ce90501e34fd06b85..289a5bbea3a6be2ac2a4d1ccd86c6c56cd404697 100644 (file)
@@ -157,6 +157,8 @@ class UniqueObjectsOutputGenerator(OutputGenerator):
             'vkGetDisplayModeProperties2KHR',
             'vkCreateRenderPass',
             'vkDestroyRenderPass',
+            'vkSetDebugUtilsObjectNameEXT',
+            'vkSetDebugUtilsObjectTagEXT',
             ]
         # Commands shadowed by interface functions and are not implemented
         self.interface_functions = [
@@ -165,10 +167,14 @@ class UniqueObjectsOutputGenerator(OutputGenerator):
             'vkGetDisplayPlaneSupportedDisplaysKHR',
             'vkGetDisplayModePropertiesKHR',
             'vkGetDisplayPlaneCapabilitiesKHR',
-            # DebugReport APIs are hooked, but handled separately in the source file
+            # VK_EXT_debug_report APIs are hooked, but handled separately in the source file
             'vkCreateDebugReportCallbackEXT',
             'vkDestroyDebugReportCallbackEXT',
             'vkDebugReportMessageEXT',
+            # VK_EXT_debug_utils APIs are hooked, but handled separately in the source file
+            'vkCreateDebugUtilsMessengerEXT',
+            'vkDestroyDebugUtilsMessengerEXT',
+            'vkSubmitDebugUtilsMessageEXT',
             ]
         self.headerVersion = None
         # Internal state - accumulators for different inner block text
index e3dbfdf98439ba05d5f113fc9f07a9115e793df1..88df867af7d657eda89dc62774c494d64cc40359 100644 (file)
@@ -1104,7 +1104,7 @@ uniqueid_set = set() # store uniqueid to make sure we don't have duplicates
 # Convert a string VUID into numerical value
 #  See "VUID Mapping Details" comment above for more info
 def convertVUID(vuid_string):
-    """Convert a string-based VUID into a numberical value"""
+    """Convert a string-based VUID into a numerical value"""
     #func_struct_update = False
     #imp_param_update = False
     if vuid_string in ['', None]: