loader: utils for managing debug report events

Now need to create & destroy callbacks as part of
vkCreateInstance, so refactor debug_report entries
into API function and work function that can be
used from the loader.

Conflicts:
	loader/debug_report.c
diff --git a/loader/debug_report.c b/loader/debug_report.c
index 35ee64e..5d3ca11 100644
--- a/loader/debug_report.c
+++ b/loader/debug_report.c
@@ -66,36 +66,50 @@
     }
 }
 
+VkResult util_CreateDebugReportCallback(
+        struct loader_instance *inst,
+        VkDebugReportCallbackCreateInfoLUNARG *pCreateInfo,
+        const VkAllocationCallbacks *pAllocator,
+        VkDebugReportCallbackLUNARG callback)
+{
+    VkLayerDbgFunctionNode *pNewDbgFuncNode;
+    if (pAllocator != NULL) {
+        pNewDbgFuncNode = (VkLayerDbgFunctionNode *) pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(VkLayerDbgFunctionNode), sizeof(uint32_t), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+    } else {
+        pNewDbgFuncNode = (VkLayerDbgFunctionNode *) loader_heap_alloc(inst, sizeof(VkLayerDbgFunctionNode), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+    }
+    if (!pNewDbgFuncNode)
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+    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_CreateDebugReportCallback(
         VkInstance instance,
         VkDebugReportCallbackCreateInfoLUNARG *pCreateInfo,
         VkAllocationCallbacks *pAllocator,
         VkDebugReportCallbackLUNARG* pCallback)
 {
-    VkLayerDbgFunctionNode *pNewDbgFuncNode = (VkLayerDbgFunctionNode *) loader_heap_alloc((struct loader_instance *)instance, sizeof(VkLayerDbgFunctionNode), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
-    if (!pNewDbgFuncNode)
-        return VK_ERROR_OUT_OF_HOST_MEMORY;
-
     struct loader_instance *inst = loader_get_instance(instance);
     loader_platform_thread_lock_mutex(&loader_lock);
     VkResult result = inst->disp->CreateDebugReportCallbackLUNARG(instance, pCreateInfo, pAllocator, pCallback);
     if (result == VK_SUCCESS) {
-        pNewDbgFuncNode->msgCallback = *pCallback;
-        pNewDbgFuncNode->pfnMsgCallback = pCreateInfo->pfnCallback;
-        pNewDbgFuncNode->msgFlags = pCreateInfo->flags;
-        pNewDbgFuncNode->pUserData = pCreateInfo->pUserData;
-        pNewDbgFuncNode->pNext = inst->DbgFunctionHead;
-        inst->DbgFunctionHead = pNewDbgFuncNode;
-    } else {
-        loader_heap_free((struct loader_instance *) instance, pNewDbgFuncNode);
+        result = util_CreateDebugReportCallback(inst, pCreateInfo, pAllocator, *pCallback);
     }
     loader_platform_thread_unlock_mutex(&loader_lock);
     return result;
 }
 
 // Utility function to handle reporting
-static inline VkBool32 debug_report_log_msg(
-    struct loader_instance              *inst,
+VkBool32 util_DebugReportMessage(
+    const struct loader_instance*       inst,
     VkFlags                             msgFlags,
     VkDebugReportObjectTypeLUNARG       objectType,
     uint64_t                            srcObject,
@@ -124,6 +138,30 @@
     return bail;
 }
 
+void util_DestroyDebugReportCallback(
+        struct loader_instance *inst,
+        VkDebugReportCallbackLUNARG 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 (pAllocator != NULL) {
+                pAllocator->pfnFree(pAllocator->pUserData, pTrav);
+            } else {
+                loader_heap_free(inst, pTrav);
+            }
+            break;
+        }
+        pPrev = pTrav;
+        pTrav = pTrav->pNext;
+    }
+}
 
 static VKAPI_ATTR void VKAPI_CALL debug_report_DestroyDebugReportCallback(
         VkInstance instance,
@@ -132,22 +170,10 @@
 {
     struct loader_instance *inst = loader_get_instance(instance);
     loader_platform_thread_lock_mutex(&loader_lock);
-    VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead;
-    VkLayerDbgFunctionNode *pPrev = pTrav;
 
     inst->disp->DestroyDebugReportCallbackLUNARG(instance, callback, pAllocator);
 
-    while (pTrav) {
-        if (pTrav->msgCallback == callback) {
-            pPrev->pNext = pTrav->pNext;
-            if (inst->DbgFunctionHead == pTrav)
-                inst->DbgFunctionHead = pTrav->pNext;
-            loader_heap_free((struct loader_instance *) instance, pTrav);
-            break;
-        }
-        pPrev = pTrav;
-        pTrav = pTrav->pNext;
-    }
+    util_DestroyDebugReportCallback(inst, callback, pAllocator);
 
     loader_platform_thread_unlock_mutex(&loader_lock);
 }
@@ -270,8 +296,11 @@
         const char*                                 pMsg)
 {
     const struct loader_icd *icd;
+
+
     struct loader_instance *inst = (struct loader_instance *) instance;
 
+    loader_platform_thread_lock_mutex(&loader_lock);
     for (icd = inst->icds; icd; icd = icd->next) {
         if (icd->DebugReportMessageLUNARG != NULL) {
             icd->DebugReportMessageLUNARG(icd->instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
@@ -282,7 +311,10 @@
      * 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.
      */
-    debug_report_log_msg(inst, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
+
+    util_DebugReportMessage(inst, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
+
+    loader_platform_thread_unlock_mutex(&loader_lock);
 }
 
 bool debug_report_instance_gpa(
diff --git a/loader/debug_report.h b/loader/debug_report.h
index 1d81275..baaae86 100644
--- a/loader/debug_report.h
+++ b/loader/debug_report.h
@@ -123,3 +123,24 @@
     int32_t                                     msgCode,
     const char*                                 pLayerPrefix,
     const char*                                 pMsg);
+
+VkResult util_CreateDebugReportCallback(
+        struct loader_instance *inst,
+        VkDebugReportCallbackCreateInfoLUNARG *pCreateInfo,
+        const VkAllocationCallbacks *pAllocator,
+        VkDebugReportCallbackLUNARG callback);
+
+void util_DestroyDebugReportCallback(
+        struct loader_instance *inst,
+        VkDebugReportCallbackLUNARG callback,
+        const VkAllocationCallbacks *pAllocator);
+
+VkBool32 util_DebugReportMessage(
+    const struct loader_instance*       inst,
+    VkFlags                             msgFlags,
+    VkDebugReportObjectTypeLUNARG       objectType,
+    uint64_t                            srcObject,
+    size_t                              location,
+    int32_t                             msgCode,
+    const char*                         pLayerPrefix,
+    const char*                         pMsg);
diff --git a/loader/trampoline.c b/loader/trampoline.c
index 6357483..58a3d2f 100644
--- a/loader/trampoline.c
+++ b/loader/trampoline.c
@@ -44,6 +44,8 @@
 {
     struct loader_instance *ptr_instance = NULL;
     VkResult res = VK_ERROR_INITIALIZATION_FAILED;
+    VkDebugReportCallbackLUNARG instance_callback = VK_NULL_HANDLE;
+    void *pNext = (void *) pCreateInfo->pNext;
 
     loader_platform_thread_once(&once_init, loader_initialize);
 
@@ -68,6 +70,17 @@
         ptr_instance->alloc_callbacks = *pAllocator;
     }
 
+    while (!pNext) {
+        if (((VkInstanceCreateInfo *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_LUNARG) {
+            instance_callback = (VkDebugReportCallbackLUNARG) ptr_instance;
+            if (util_CreateDebugReportCallback(ptr_instance, pNext, pAllocator, instance_callback)) {
+                free(ptr_instance);
+                loader_platform_thread_unlock_mutex(&loader_lock);
+                return VK_ERROR_OUT_OF_HOST_MEMORY;
+            }
+        }
+    }
+
     /* Due to implicit layers need to get layer list even if
      * enabledLayerNameCount == 0 and VK_INSTANCE_LAYERS is unset. For now always
      * get layer list (both instance and device) via loader_layer_scan(). */