loader: implement new layer init method
authorCourtney Goeltzenleuchter <courtneygo@google.com>
Fri, 8 Jan 2016 19:18:43 +0000 (12:18 -0700)
committerJon Ashburn <jon@lunarg.com>
Thu, 21 Jan 2016 01:04:55 +0000 (18:04 -0700)
New layer init method requires the construction of
Link information for CreateInstance and CreateDevice
that is accessible to layers via the CreateInfo.pNext pointer.
The layer can then use the Get*ProcAddr from the Link
structure to initialize their dispatch table if the
call down the chain returns successfully.
This removes the need to do special initialization work
at Get*ProcAddr time.
Layer Get*ProcAddr now return their internal function
pointers regardless of the value of instance or device.
Only need to have valid instance & device when looking
up extensions or when passing the request down the chain.
This mechanism allows us to remove object wrapping used
by the loader previously. Also simplifies the dispatch table
setup.

Conflicts:
layers/device_limits.cpp
layers/draw_state.cpp
loader/loader.c
loader/trampoline.c

21 files changed:
include/vulkan/vk_layer.h
layers/api_dump.h
layers/basic.cpp
layers/device_limits.cpp
layers/draw_state.cpp
layers/image.cpp
layers/mem_tracker.cpp
layers/multi.cpp
layers/object_tracker.h
layers/param_checker.cpp
layers/screenshot.cpp
layers/swapchain.cpp
layers/unique_objects.h
layers/vk_layer_table.cpp
layers/vk_layer_table.h
loader/loader.c
loader/loader.h
loader/table_ops.h
loader/trampoline.c
vk-generate.py
vk-layer-generate.py

index 6899182..da19ddd 100644 (file)
@@ -26,7 +26,6 @@ typedef struct VkBaseLayerObject_
 typedef struct VkLayerDispatchTable_
 {
     PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
-    PFN_vkCreateDevice CreateDevice;
     PFN_vkDestroyDevice DestroyDevice;
     PFN_vkGetDeviceQueue GetDeviceQueue;
     PFN_vkQueueSubmit QueueSubmit;
@@ -159,6 +158,7 @@ typedef struct VkLayerInstanceDispatchTable_
     PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
     PFN_vkCreateInstance CreateInstance;
     PFN_vkDestroyInstance DestroyInstance;
+    PFN_vkCreateDevice CreateDevice;
     PFN_vkEnumeratePhysicalDevices EnumeratePhysicalDevices;
     PFN_vkGetPhysicalDeviceFeatures GetPhysicalDeviceFeatures;
     PFN_vkGetPhysicalDeviceImageFormatProperties GetPhysicalDeviceImageFormatProperties;
@@ -223,15 +223,51 @@ typedef enum VkLayerDbgAction_
 
 // ------------------------------------------------------------------------------------------------
 // CreateInstance and CreateDevice support structures
+
+typedef enum VkLayerFunction_
+{
+    VK_LAYER_LINK_INFO = 0,
+    VK_LAYER_DEVICE_INFO = 1,
+    VK_LAYER_INSTANCE_INFO = 2
+} VkLayerFunction;
+
+/*
+ * When creating the device chain the loader needs to pass
+ * down information about it's device structure needed at
+ * the end of the chain. Passing the data via the
+ * VkLayerDeviceInfo avoids issues with finding the
+ * exact instance being used.
+ */
+typedef struct VkLayerInstanceInfo_ {
+    void *instance_info;
+    PFN_vkGetInstanceProcAddr pfnNextGetInstanceProcAddr;
+} VkLayerInstanceInfo;
+
 typedef struct VkLayerInstanceLink_ {
     struct VkLayerInstanceLink_* pNext;
     PFN_vkGetInstanceProcAddr pfnNextGetInstanceProcAddr;
 } VkLayerInstanceLink;
 
+/*
+ * When creating the device chain the loader needs to pass
+ * down information about it's device structure needed at
+ * the end of the chain. Passing the data via the
+ * VkLayerDeviceInfo avoids issues with finding the
+ * exact instance being used.
+ */
+typedef struct VkLayerDeviceInfo_ {
+    void *device_info;
+    PFN_vkGetInstanceProcAddr pfnNextGetInstanceProcAddr;
+} VkLayerDeviceInfo;
+
 typedef struct {
     VkStructureType sType; // VK_STRUCTURE_TYPE_LAYER_INSTANCE_CREATE_INFO
     const void* pNext;
-    VkLayerInstanceLink* pLayerInfo;
+    VkLayerFunction function;
+    union {
+        VkLayerInstanceLink* pLayerInfo;
+        VkLayerInstanceInfo instanceInfo;
+    } u;
 } VkLayerInstanceCreateInfo;
 
 typedef struct VkLayerDeviceLink_ {
@@ -243,7 +279,11 @@ typedef struct VkLayerDeviceLink_ {
 typedef struct {
     VkStructureType sType; // VK_STRUCTURE_TYPE_LAYER_DEVICE_CREATE_INFO
     const void* pNext;
-    VkLayerDeviceLink* pLayerInfo;
+    VkLayerFunction function;
+    union {
+        VkLayerDeviceLink* pLayerInfo;
+        VkLayerDeviceInfo deviceInfo;
+    } u;
 } VkLayerDeviceCreateInfo;
 
 // ------------------------------------------------------------------------------------------------
index 3dc8e2f..73c6a49 100644 (file)
@@ -125,3 +125,34 @@ static void createInstanceRegisterExtensions(const VkInstanceCreateInfo* pCreate
     }
 }
 
+VkResult
+explicit_CreateDevice(
+    VkPhysicalDevice         gpu,
+    const VkDeviceCreateInfo *pCreateInfo,
+    const VkAllocationCallbacks   *pAllocator,
+    VkDevice                 *pDevice)
+{
+    VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
+
+    assert(chain_info->u.pLayerInfo);
+    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
+    PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
+    PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice) fpGetInstanceProcAddr(NULL, "vkCreateDevice");
+    if (fpCreateDevice == NULL) {
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
+    // Advance the link info for the next element on the chain
+    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
+
+    VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
+    if (result != VK_SUCCESS) {
+        return result;
+    }
+
+    initDeviceTable(*pDevice, fpGetDeviceProcAddr);
+
+    createDeviceRegisterExtensions(pCreateInfo, *pDevice);
+
+    return result;
+}
index 77b08c0..45cb999 100644 (file)
@@ -95,6 +95,32 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionPropert
     }
 }
 
+VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL basic_CreateInstance(
+    const VkInstanceCreateInfo* pCreateInfo,
+    const VkAllocationCallbacks* pAllocator,
+    VkInstance* pInstance)
+{
+    VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
+
+    assert(chain_info->u.pLayerInfo);
+    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
+    PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance) fpGetInstanceProcAddr(NULL, "vkCreateInstance");
+    if (fpCreateInstance == NULL) {
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
+    // Advance the link info for the next element on the chain
+    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
+
+    VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
+    if (result != VK_SUCCESS)
+        return result;
+
+    initInstanceTable(*pInstance, fpGetInstanceProcAddr);
+
+    return result;
+}
+
 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL basic_EnumeratePhysicalDevices(
                                             VkInstance instance,
                                             uint32_t* pPhysicalDeviceCount,
@@ -106,11 +132,31 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL basic_EnumeratePhysicalDevices(
     return result;
 }
 
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL basic_CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice)
+VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL basic_CreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice)
 {
-    printf("At start of wrapped vkCreateDevice() call w/ gpu: %p\n", (void*)gpu);
-    VkResult result = device_dispatch_table(*pDevice)->CreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
-    printf("Completed wrapped vkCreateDevice() call w/ pDevice, Device %p: %p\n", (void*)pDevice, (void *) *pDevice);
+    printf("VK_LAYER_LUNARG_Basic: At start of vkCreateDevice() call w/ gpu: %p\n", (void*)physicalDevice);
+
+    VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
+
+    assert(chain_info->u.pLayerInfo);
+    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
+    PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
+    PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice) fpGetInstanceProcAddr(NULL, "vkCreateDevice");
+    if (fpCreateDevice == NULL) {
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
+    // Advance the link info for the next element on the chain
+    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
+
+    VkResult result = fpCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
+    if (result != VK_SUCCESS) {
+        return result;
+    }
+
+    initDeviceTable(*pDevice, fpGetDeviceProcAddr);
+
+    printf("VK_LAYER_LUNARG_Basic: Completed vkCreateDevice() call w/ pDevice, Device %p: %p\n", (void*)pDevice, (void *) *pDevice);
     return result;
 }
 
@@ -139,51 +185,43 @@ VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL basic_GetPhysicalDeviceFormatProperti
 
 VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char* pName)
 {
-    if (device == NULL)
-        return NULL;
-
-    /* loader uses this to force layer initialization; device object is wrapped */
-    if (!strcmp("vkGetDeviceProcAddr", pName)) {
-        initDeviceTable((const VkBaseLayerObject *) device);
+    if (!strcmp("vkGetDeviceProcAddr", pName))
         return (PFN_vkVoidFunction) vkGetDeviceProcAddr;
-    }
-
-    if (!strcmp("vkCreateDevice", pName))
-        return (PFN_vkVoidFunction) basic_CreateDevice;
     if (!strcmp("vkDestroyDevice", pName))
         return (PFN_vkVoidFunction) basic_DestroyDevice;
     if (!strcmp("vkLayerExtension1", pName))
         return (PFN_vkVoidFunction) vkLayerExtension1;
-    else
-    {
-        if (device_dispatch_table(device)->GetDeviceProcAddr == NULL)
-            return NULL;
-        return device_dispatch_table(device)->GetDeviceProcAddr(device, pName);
-    }
+
+    if (device == NULL)
+        return NULL;
+
+    if (device_dispatch_table(device)->GetDeviceProcAddr == NULL)
+        return NULL;
+    return device_dispatch_table(device)->GetDeviceProcAddr(device, pName);
 }
 
 VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char* pName)
 {
-    if (instance == NULL)
-        return NULL;
-
-    /* loader uses this to force layer initialization; instance object is wrapped */
-    if (!strcmp("vkGetInstanceProcAddr", pName)) {
-        initInstanceTable((const VkBaseLayerObject *) instance);
+    if (!strcmp("vkGetInstanceProcAddr", pName))
         return (PFN_vkVoidFunction) vkGetInstanceProcAddr;
-    }
-
     if (!strcmp("vkEnumerateDeviceLayerProperties", pName))
         return (PFN_vkVoidFunction) vkEnumerateDeviceLayerProperties;
     if (!strcmp("vkEnumerateDeviceExtensionProperties", pName))
         return (PFN_vkVoidFunction) vkEnumerateDeviceExtensionProperties;
     if (!strcmp("vkGetPhysicalDeviceFormatProperties", pName))
         return (PFN_vkVoidFunction) basic_GetPhysicalDeviceFormatProperties;
+    if (!strcmp("vkCreateInstance", pName))
+        return (PFN_vkVoidFunction) basic_CreateInstance;
     if (!strcmp("vkDestroyInstance", pName))
         return (PFN_vkVoidFunction) basic_DestroyInstance;
+    if (!strcmp("vkCreateDevice", pName))
+        return (PFN_vkVoidFunction) basic_CreateDevice;
     if (!strcmp("vkEnumeratePhysicalDevices", pName))
         return (PFN_vkVoidFunction) basic_EnumeratePhysicalDevices;
 
+    if (instance == NULL)
+        return NULL;
+
     if (instance_dispatch_table(instance)->GetInstanceProcAddr == NULL)
         return NULL;
     return instance_dispatch_table(instance)->GetInstanceProcAddr(instance, pName);
index fbb9af3..24df64e 100644 (file)
@@ -43,6 +43,7 @@
 #endif
 #include "vk_struct_size_helper.h"
 #include "device_limits.h"
+#include "vulkan/vk_layer.h"
 #include "vk_layer_config.h"
 #include "vulkan/vk_debug_marker_layer.h"
 #include "vk_layer_table.h"
@@ -183,21 +184,36 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerPropertie
 
 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance)
 {
-    layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
-    VkLayerInstanceDispatchTable* pTable = my_data->instance_dispatch_table;
-    VkResult result = pTable->CreateInstance(pCreateInfo, pAllocator, pInstance);
-
-    if (result == VK_SUCCESS) {
-        my_data->report_data = debug_report_create_instance(
-                                   pTable,
-                                   *pInstance,
-                                   pCreateInfo->enabledExtensionCount,
-                                   pCreateInfo->ppEnabledExtensionNames);
-
-        init_device_limits(my_data, pAllocator);
-        my_data->instanceState = unique_ptr<INSTANCE_STATE>(new INSTANCE_STATE());
+    VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
+
+    assert(chain_info->u.pLayerInfo);
+    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
+    PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance) fpGetInstanceProcAddr(NULL, "vkCreateInstance");
+    if (fpCreateInstance == NULL) {
+        return VK_ERROR_INITIALIZATION_FAILED;
     }
-    return result;
+
+    // Advance the link info for the next element on the chain
+    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
+
+    VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
+    if (result != VK_SUCCESS)
+        return result;
+
+    layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
+    my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
+    layer_init_instance_dispatch_table(*pInstance, my_data->instance_dispatch_table, fpGetInstanceProcAddr);
+
+    my_data->report_data = debug_report_create_instance(
+                               my_data->instance_dispatch_table,
+                               *pInstance,
+                               pCreateInfo->enabledExtensionCount,
+                               pCreateInfo->ppEnabledExtensionNames);
+
+    init_device_limits(my_data, pAllocator);
+    my_data->instanceState = unique_ptr<INSTANCE_STATE>(new INSTANCE_STATE());
+
+    return VK_SUCCESS;
 }
 
 /* hook DestroyInstance to remove tableInstanceMap entry */
@@ -448,17 +464,34 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(VkPhysicalDevice g
     if (skipCall)
         return VK_ERROR_VALIDATION_FAILED_EXT;
 
-    layer_data *device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
-    VkResult result = device_data->device_dispatch_table->CreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
-    if (result == VK_SUCCESS) {
-        device_data->report_data = layer_debug_report_create_device(phy_dev_data->report_data, *pDevice);
-        createDeviceRegisterExtensions(pCreateInfo, *pDevice);
-        device_data->physicalDevice = gpu;
+    VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
 
-        // Get physical device properties for this device
-        phy_dev_data->instance_dispatch_table->GetPhysicalDeviceProperties(gpu, &(phy_dev_data->physDevPropertyMap[*pDevice]));
+    assert(chain_info->u.pLayerInfo);
+    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
+    PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
+    PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice) fpGetInstanceProcAddr(NULL, "vkCreateDevice");
+    if (fpCreateDevice == NULL) {
+        return VK_ERROR_INITIALIZATION_FAILED;
     }
 
+    // Advance the link info for the next element on the chain
+    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
+
+    VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
+    if (result != VK_SUCCESS) {
+        return result;
+    }
+
+    layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(gpu), layer_data_map);
+    layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
+    my_device_data->device_dispatch_table = new VkLayerDispatchTable;
+    layer_init_device_dispatch_table(*pDevice, my_device_data->device_dispatch_table, fpGetDeviceProcAddr);
+    my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
+    my_device_data->physicalDevice = gpu;
+    createDeviceRegisterExtensions(pCreateInfo, *pDevice);
+
+    // Get physical device properties for this device
+    phy_dev_data->instance_dispatch_table->GetPhysicalDeviceProperties(gpu, &(phy_dev_data->physDevPropertyMap[*pDevice]));
     return result;
 }
 
@@ -685,21 +718,8 @@ VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDebugReportMessageEXT(
 
 VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char* funcName)
 {
-    if (dev == NULL)
-        return NULL;
-
-    layer_data *my_data;
-    /* loader uses this to force layer initialization; device object is wrapped */
-    if (!strcmp(funcName, "vkGetDeviceProcAddr")) {
-        VkBaseLayerObject* wrapped_dev = (VkBaseLayerObject*) dev;
-        my_data = get_my_data_ptr(get_dispatch_key(wrapped_dev->baseObject), layer_data_map);
-        my_data->device_dispatch_table = new VkLayerDispatchTable;
-        layer_initialize_dispatch_table(my_data->device_dispatch_table, wrapped_dev);
+    if (!strcmp(funcName, "vkGetDeviceProcAddr"))
         return (PFN_vkVoidFunction) vkGetDeviceProcAddr;
-    }
-    my_data = get_my_data_ptr(get_dispatch_key(dev), layer_data_map);
-    if (!strcmp(funcName, "vkCreateDevice"))
-        return (PFN_vkVoidFunction) vkCreateDevice;
     if (!strcmp(funcName, "vkDestroyDevice"))
         return (PFN_vkVoidFunction) vkDestroyDevice;
     if (!strcmp(funcName, "vkGetDeviceQueue"))
@@ -723,6 +743,10 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkD
     if (!strcmp(funcName, "vkCmdFillBuffer"))
         return (PFN_vkVoidFunction) vkCmdFillBuffer;
 
+    if (dev == NULL)
+        return NULL;
+
+    layer_data *my_data = get_my_data_ptr(get_dispatch_key(dev), layer_data_map);
     VkLayerDispatchTable* pTable = my_data->device_dispatch_table;
     {
         if (pTable->GetDeviceProcAddr == NULL)
@@ -734,23 +758,18 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkD
 VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char* funcName)
 {
     PFN_vkVoidFunction fptr;
-    if (instance == NULL)
-        return NULL;
 
     layer_data *my_data;
-    /* loader uses this to force layer initialization; instance object is wrapped */
-    if (!strcmp(funcName, "vkGetInstanceProcAddr")) {
-        VkBaseLayerObject* wrapped_inst = (VkBaseLayerObject*) instance;
-        my_data = get_my_data_ptr(get_dispatch_key(wrapped_inst->baseObject), layer_data_map);
-        my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
-        layer_init_instance_dispatch_table(my_data->instance_dispatch_table, wrapped_inst);
+    if (!strcmp(funcName, "vkGetInstanceProcAddr"))
         return (PFN_vkVoidFunction) vkGetInstanceProcAddr;
-    }
-    my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
+    if (!strcmp(funcName, "vkGetDeviceProcAddr"))
+        return (PFN_vkVoidFunction) vkGetDeviceProcAddr;
     if (!strcmp(funcName, "vkCreateInstance"))
         return (PFN_vkVoidFunction) vkCreateInstance;
     if (!strcmp(funcName, "vkDestroyInstance"))
         return (PFN_vkVoidFunction) vkDestroyInstance;
+    if (!strcmp(funcName, "vkCreateDevice"))
+        return (PFN_vkVoidFunction) vkCreateDevice;
     if (!strcmp(funcName, "vkEnumeratePhysicalDevices"))
         return (PFN_vkVoidFunction) vkEnumeratePhysicalDevices;
     if (!strcmp(funcName, "vkGetPhysicalDeviceFeatures"))
@@ -772,6 +791,10 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(V
     if (!strcmp(funcName, "vkEnumerateInstanceExtensionProperties"))
         return (PFN_vkVoidFunction) vkEnumerateInstanceExtensionProperties;
 
+    if (!instance) return NULL;
+
+    my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
+
     fptr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);
     if (fptr)
         return fptr;
index c85598d..8d6ac65 100644 (file)
@@ -2813,21 +2813,34 @@ static void init_draw_state(layer_data *my_data, const VkAllocationCallbacks *pA
 
 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance)
 {
-    // TODOSC : Shouldn't need any customization here
+    VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
+
+    assert(chain_info->u.pLayerInfo);
+    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
+    PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance) fpGetInstanceProcAddr(NULL, "vkCreateInstance");
+    if (fpCreateInstance == NULL) {
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
+    // Advance the link info for the next element on the chain
+    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
+
+    VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
+    if (result != VK_SUCCESS)
+        return result;
+
     layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
-    VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
-    VkResult result = pTable->CreateInstance(pCreateInfo, pAllocator, pInstance);
+    my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
+    layer_init_instance_dispatch_table(*pInstance, my_data->instance_dispatch_table, fpGetInstanceProcAddr);
 
-    if (result == VK_SUCCESS) {
-        layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
-        my_data->report_data = debug_report_create_instance(
-                                   pTable,
-                                   *pInstance,
-                                   pCreateInfo->enabledExtensionCount,
-                                   pCreateInfo->ppEnabledExtensionNames);
+    my_data->report_data = debug_report_create_instance(
+                               my_data->instance_dispatch_table,
+                               *pInstance,
+                               pCreateInfo->enabledExtensionCount,
+                               pCreateInfo->ppEnabledExtensionNames);
+
+    init_draw_state(my_data, pAllocator);
 
-        init_draw_state(my_data, pAllocator);
-    }
     return result;
 }
 
@@ -2890,16 +2903,35 @@ static void createDeviceRegisterExtensions(const VkDeviceCreateInfo* pCreateInfo
 
 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice)
 {
-    layer_data *instance_data = get_my_data_ptr(get_dispatch_key(gpu), layer_data_map);
-    layer_data *dev_data      = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
-    VkResult    result        = dev_data->device_dispatch_table->CreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
+    VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
 
-    if (result == VK_SUCCESS) {
-        dev_data->report_data = layer_debug_report_create_device(instance_data->report_data, *pDevice);
-        createDeviceRegisterExtensions(pCreateInfo, *pDevice);
-        // Get physical device limits for this device
-        instance_data->instance_dispatch_table->GetPhysicalDeviceProperties(gpu, &(instance_data->physDevPropertyMap[*pDevice]));
+    assert(chain_info->u.pLayerInfo);
+    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
+    PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
+    PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice) fpGetInstanceProcAddr(NULL, "vkCreateDevice");
+    if (fpCreateDevice == NULL) {
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
+    // Advance the link info for the next element on the chain
+    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
+
+    VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
+    if (result != VK_SUCCESS) {
+        return result;
     }
+
+    layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(gpu), layer_data_map);
+    layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
+
+    // Setup device dispatch table
+    my_device_data->device_dispatch_table = new VkLayerDispatchTable;
+    layer_init_device_dispatch_table(*pDevice, my_device_data->device_dispatch_table, fpGetDeviceProcAddr);
+
+    my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
+    createDeviceRegisterExtensions(pCreateInfo, *pDevice);
+    // Get physical device limits for this device
+    my_instance_data->instance_dispatch_table->GetPhysicalDeviceProperties(gpu, &(my_instance_data->physDevPropertyMap[*pDevice]));
     return result;
 }
 
@@ -6088,21 +6120,8 @@ VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdDbgMarkerEnd(VkCommandBuffer com
 
 VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char* funcName)
 {
-    if (dev == NULL)
-        return NULL;
-
-    layer_data *dev_data;
-    /* loader uses this to force layer initialization; device object is wrapped */
-    if (!strcmp(funcName, "vkGetDeviceProcAddr")) {
-        VkBaseLayerObject* wrapped_dev = (VkBaseLayerObject*) dev;
-        dev_data = get_my_data_ptr(get_dispatch_key(wrapped_dev->baseObject), layer_data_map);
-        dev_data->device_dispatch_table = new VkLayerDispatchTable;
-        layer_initialize_dispatch_table(dev_data->device_dispatch_table, wrapped_dev);
+    if (!strcmp(funcName, "vkGetDeviceProcAddr"))
         return (PFN_vkVoidFunction) vkGetDeviceProcAddr;
-    }
-    dev_data = get_my_data_ptr(get_dispatch_key(dev), layer_data_map);
-    if (!strcmp(funcName, "vkCreateDevice"))
-        return (PFN_vkVoidFunction) vkCreateDevice;
     if (!strcmp(funcName, "vkDestroyDevice"))
         return (PFN_vkVoidFunction) vkDestroyDevice;
     if (!strcmp(funcName, "vkQueueSubmit"))
@@ -6306,6 +6325,12 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkD
     if (!strcmp(funcName, "vkCreateSemaphore"))
         return (PFN_vkVoidFunction) vkCreateSemaphore;
 
+    if (dev == NULL)
+        return NULL;
+
+    layer_data *dev_data;
+    dev_data = get_my_data_ptr(get_dispatch_key(dev), layer_data_map);
+
     if (dev_data->device_extensions.wsi_enabled)
     {
         if (!strcmp(funcName, "vkCreateSwapchainKHR"))
@@ -6337,21 +6362,14 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkD
 
 VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char* funcName)
 {
-    PFN_vkVoidFunction fptr;
-    if (instance == NULL)
-        return NULL;
-
-    layer_data* my_data;
-    /* loader uses this to force layer initialization; instance object is wrapped */
-    if (!strcmp(funcName, "vkGetInstanceProcAddr")) {
-        VkBaseLayerObject* wrapped_inst = (VkBaseLayerObject*) instance;
-        my_data = get_my_data_ptr(get_dispatch_key(wrapped_inst->baseObject), layer_data_map);
-        my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
-        layer_init_instance_dispatch_table(my_data->instance_dispatch_table, wrapped_inst);
+    if (!strcmp(funcName, "vkGetInstanceProcAddr"))
         return (PFN_vkVoidFunction) vkGetInstanceProcAddr;
-    }
+    if (!strcmp(funcName, "vkGetDeviceProcAddr"))
+        return (PFN_vkVoidFunction) vkGetDeviceProcAddr;
     if (!strcmp(funcName, "vkCreateInstance"))
         return (PFN_vkVoidFunction) vkCreateInstance;
+    if (!strcmp(funcName, "vkCreateDevice"))
+        return (PFN_vkVoidFunction) vkCreateDevice;
     if (!strcmp(funcName, "vkDestroyInstance"))
         return (PFN_vkVoidFunction) vkDestroyInstance;
     if (!strcmp(funcName, "vkEnumerateInstanceLayerProperties"))
@@ -6363,15 +6381,19 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(V
     if (!strcmp(funcName, "vkEnumerateDeviceExtensionProperties"))
         return (PFN_vkVoidFunction) vkEnumerateDeviceExtensionProperties;
 
+    if (instance == NULL)
+        return NULL;
+
+    PFN_vkVoidFunction fptr;
+
+    layer_data* my_data;
     my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
     fptr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);
     if (fptr)
         return fptr;
 
-    {
-        VkLayerInstanceDispatchTable* pTable = my_data->instance_dispatch_table;
-        if (pTable->GetInstanceProcAddr == NULL)
-            return NULL;
-        return pTable->GetInstanceProcAddr(instance, funcName);
-    }
+    VkLayerInstanceDispatchTable* pTable = my_data->instance_dispatch_table;
+    if (pTable->GetInstanceProcAddr == NULL)
+        return NULL;
+    return pTable->GetInstanceProcAddr(instance, funcName);
 }
index 1281dfb..f371bdc 100644 (file)
@@ -146,16 +146,34 @@ VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDebugReportMessageEXT(
 
 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance)
 {
+    VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
+
+    assert(chain_info->u.pLayerInfo);
+    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
+    PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance) fpGetInstanceProcAddr(NULL, "vkCreateInstance");
+    if (fpCreateInstance == NULL) {
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
+    // Advance the link info for the next element on the chain
+    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
+
+    VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
+    if (result != VK_SUCCESS)
+        return result;
+
     layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
-    VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
-    VkResult result = pTable->CreateInstance(pCreateInfo, pAllocator, pInstance);
+    my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
+    layer_init_instance_dispatch_table(*pInstance, my_data->instance_dispatch_table, fpGetInstanceProcAddr);
 
-    if (result == VK_SUCCESS) {
-        my_data->report_data = debug_report_create_instance(pTable, *pInstance, pCreateInfo->enabledExtensionCount,
-            pCreateInfo->ppEnabledExtensionNames);
+    my_data->report_data = debug_report_create_instance(
+                               my_data->instance_dispatch_table,
+                               *pInstance,
+                               pCreateInfo->enabledExtensionCount,
+                               pCreateInfo->ppEnabledExtensionNames);
+
+    InitImage(my_data, pAllocator);
 
-        InitImage(my_data, pAllocator);
-    }
     return result;
 }
 
@@ -182,16 +200,35 @@ VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance
 
 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice)
 {
-    layer_data *instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
-    layer_data *device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
-    VkResult result = device_data->device_dispatch_table->CreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
-    if(result == VK_SUCCESS)
-    {
-        device_data->report_data = layer_debug_report_create_device(instance_data->report_data, *pDevice);
-        device_data->physicalDevice = physicalDevice;
+    VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
+
+    assert(chain_info->u.pLayerInfo);
+    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
+    PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
+    PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice) fpGetInstanceProcAddr(NULL, "vkCreateDevice");
+    if (fpCreateDevice == NULL) {
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
+    // Advance the link info for the next element on the chain
+    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
+
+    VkResult result = fpCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
+    if (result != VK_SUCCESS) {
+        return result;
     }
 
-    instance_data->instance_dispatch_table->GetPhysicalDeviceProperties(physicalDevice, &(device_data->physicalDeviceProperties));
+    layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
+    layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
+
+    // Setup device dispatch table
+    my_device_data->device_dispatch_table = new VkLayerDispatchTable;
+    layer_init_device_dispatch_table(*pDevice, my_device_data->device_dispatch_table, fpGetDeviceProcAddr);
+
+    my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
+    my_device_data->physicalDevice = physicalDevice;
+
+    my_instance_data->instance_dispatch_table->GetPhysicalDeviceProperties(physicalDevice, &(my_device_data->physicalDeviceProperties));
 
     return result;
 }
@@ -1141,23 +1178,8 @@ VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties(VkPhysi
 
 VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char* funcName)
 {
-    if (device == NULL) {
-        return NULL;
-    }
-
-    layer_data *my_data;
-    // loader uses this to force layer initialization; device object is wrapped
-    if (!strcmp(funcName, "vkGetDeviceProcAddr")) {
-        VkBaseLayerObject* wrapped_dev = (VkBaseLayerObject*) device;
-        my_data = get_my_data_ptr(get_dispatch_key(wrapped_dev->baseObject), layer_data_map);
-        my_data->device_dispatch_table = new VkLayerDispatchTable;
-        layer_initialize_dispatch_table(my_data->device_dispatch_table, wrapped_dev);
+    if (!strcmp(funcName, "vkGetDeviceProcAddr"))
         return (PFN_vkVoidFunction) vkGetDeviceProcAddr;
-    }
-
-    my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
-    if (!strcmp(funcName, "vkCreateDevice"))
-        return (PFN_vkVoidFunction) vkCreateDevice;
     if (!strcmp(funcName, "vkDestroyDevice"))
         return (PFN_vkVoidFunction) vkDestroyDevice;
     if (!strcmp(funcName, "vkCreateImage"))
@@ -1189,6 +1211,12 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkD
     if (!strcmp(funcName, "vkGetImageSubresourceLayout"))
         return (PFN_vkVoidFunction) vkGetImageSubresourceLayout;
 
+    if (device == NULL) {
+        return NULL;
+    }
+
+    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
+
     VkLayerDispatchTable* pTable = my_data->device_dispatch_table;
     {
         if (pTable->GetDeviceProcAddr == NULL)
@@ -1199,25 +1227,14 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkD
 
 VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char* funcName)
 {
-    if (instance == NULL) {
-        return NULL;
-    }
-
-    layer_data *my_data;
-    // loader uses this to force layer initialization; instance object is wrapped
-    if (!strcmp(funcName, "vkGetInstanceProcAddr")) {
-        VkBaseLayerObject* wrapped_inst = (VkBaseLayerObject*) instance;
-        my_data = get_my_data_ptr(get_dispatch_key(wrapped_inst->baseObject), layer_data_map);
-        my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
-        layer_init_instance_dispatch_table(my_data->instance_dispatch_table, wrapped_inst);
+    if (!strcmp(funcName, "vkGetInstanceProcAddr"))
         return (PFN_vkVoidFunction) vkGetInstanceProcAddr;
-    }
-
-    my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
     if (!strcmp(funcName, "vkCreateInstance"))
         return (PFN_vkVoidFunction) vkCreateInstance;
     if (!strcmp(funcName, "vkDestroyInstance"))
         return (PFN_vkVoidFunction) vkDestroyInstance;
+    if (!strcmp(funcName, "vkCreateDevice"))
+        return (PFN_vkVoidFunction) vkCreateDevice;
     if (!strcmp(funcName, "vkEnumerateInstanceLayerProperties"))
         return (PFN_vkVoidFunction) vkEnumerateInstanceLayerProperties;
     if (!strcmp(funcName, "vkEnumerateInstanceExtensionProperties"))
@@ -1229,14 +1246,18 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(V
     if (!strcmp(funcName, "vkGetPhysicalDeviceProperties"))
         return (PFN_vkVoidFunction) vkGetPhysicalDeviceProperties;
 
+    if (instance == NULL) {
+        return NULL;
+    }
+
+    layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
+
     PFN_vkVoidFunction fptr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);
     if(fptr)
         return fptr;
 
-    {
-        VkLayerInstanceDispatchTable* pTable = my_data->instance_dispatch_table;
-        if (pTable->GetInstanceProcAddr == NULL)
-            return NULL;
-        return pTable->GetInstanceProcAddr(instance, funcName);
-    }
+    VkLayerInstanceDispatchTable* pTable = my_data->instance_dispatch_table;
+    if (pTable->GetInstanceProcAddr == NULL)
+        return NULL;
+    return pTable->GetInstanceProcAddr(instance, funcName);
 }
index b621c6e..afcc7cd 100644 (file)
@@ -1119,19 +1119,35 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(
     const VkAllocationCallbacks*                pAllocator,
     VkInstance*                                 pInstance)
 {
-    layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
-    VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
-    VkResult result = pTable->CreateInstance(pCreateInfo, pAllocator, pInstance);
+    VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
 
-    if (result == VK_SUCCESS) {
-        my_data->report_data = debug_report_create_instance(
-                                   pTable,
-                                   *pInstance,
-                                   pCreateInfo->enabledExtensionCount,
-                                   pCreateInfo->ppEnabledExtensionNames);
+    assert(chain_info->u.pLayerInfo);
+    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
+    PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance) fpGetInstanceProcAddr(NULL, "vkCreateInstance");
+    if (fpCreateInstance == NULL) {
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
+    // Advance the link info for the next element on the chain
+    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
 
-        init_mem_tracker(my_data, pAllocator);
+    VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
+    if (result != VK_SUCCESS) {
+        return result;
     }
+
+    layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
+    my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
+    layer_init_instance_dispatch_table(*pInstance, my_data->instance_dispatch_table, fpGetInstanceProcAddr);
+
+    my_data->report_data = debug_report_create_instance(
+                               my_data->instance_dispatch_table,
+                               *pInstance,
+                               pCreateInfo->enabledExtensionCount,
+                               pCreateInfo->ppEnabledExtensionNames);
+
+    init_mem_tracker(my_data, pAllocator);
+
     return result;
 }
 
@@ -1161,15 +1177,35 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(
     const VkAllocationCallbacks *pAllocator,
     VkDevice                    *pDevice)
 {
-    layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
-    VkLayerDispatchTable *pDeviceTable = my_device_data->device_dispatch_table;
-    VkResult result = pDeviceTable->CreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
-    if (result == VK_SUCCESS) {
-        layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(gpu), layer_data_map);
-        my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
-        createDeviceRegisterExtensions(pCreateInfo, *pDevice);
-        my_instance_data->instance_dispatch_table->GetPhysicalDeviceProperties(gpu, &my_device_data->properties);
+    VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
+
+    assert(chain_info->u.pLayerInfo);
+    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
+    PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
+    PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice) fpGetInstanceProcAddr(NULL, "vkCreateDevice");
+    if (fpCreateDevice == NULL) {
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
+    // Advance the link info for the next element on the chain
+    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
+
+    VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
+    if (result != VK_SUCCESS) {
+        return result;
     }
+
+    layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(gpu), layer_data_map);
+    layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
+
+    // Setup device dispatch table
+    my_device_data->device_dispatch_table = new VkLayerDispatchTable;
+    layer_init_device_dispatch_table(*pDevice, my_device_data->device_dispatch_table, fpGetDeviceProcAddr);
+
+    my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
+    createDeviceRegisterExtensions(pCreateInfo, *pDevice);
+    my_instance_data->instance_dispatch_table->GetPhysicalDeviceProperties(gpu, &my_device_data->properties);
+
     return result;
 }
 
@@ -3192,20 +3228,8 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(
     VkDevice    dev,
     const char *funcName)
 {
-    if (dev == NULL)
-        return NULL;
-
-    layer_data *my_data;
-    /* loader uses this to force layer initialization; device object is wrapped */
-    if (!strcmp(funcName, "vkGetDeviceProcAddr")) {
-        VkBaseLayerObject* wrapped_dev = (VkBaseLayerObject*) dev;
-        my_data = get_my_data_ptr(get_dispatch_key(wrapped_dev->baseObject), layer_data_map);
-        my_data->device_dispatch_table = new VkLayerDispatchTable;
-        layer_initialize_dispatch_table(my_data->device_dispatch_table, wrapped_dev);
+    if (!strcmp(funcName, "vkGetDeviceProcAddr"))
         return (PFN_vkVoidFunction) vkGetDeviceProcAddr;
-    }
-    if (!strcmp(funcName, "vkCreateDevice"))
-        return (PFN_vkVoidFunction) vkCreateDevice;
     if (!strcmp(funcName, "vkDestroyDevice"))
         return (PFN_vkVoidFunction) vkDestroyDevice;
     if (!strcmp(funcName, "vkQueueSubmit"))
@@ -3332,6 +3356,10 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(
         return (PFN_vkVoidFunction) vkDestroyFramebuffer;
 
 
+    if (dev == NULL)
+        return NULL;
+
+    layer_data *my_data;
     my_data = get_my_data_ptr(get_dispatch_key(dev), layer_data_map);
     if (my_data->wsi_enabled)
     {
@@ -3358,25 +3386,19 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(
     const char *funcName)
 {
     PFN_vkVoidFunction fptr;
-    if (instance == NULL)
-        return NULL;
 
-    layer_data *my_data;
-    /* loader uses this to force layer initialization; instance object is wrapped */
-    if (!strcmp(funcName, "vkGetInstanceProcAddr")) {
-        VkBaseLayerObject* wrapped_inst = (VkBaseLayerObject*) instance;
-        my_data = get_my_data_ptr(get_dispatch_key(wrapped_inst->baseObject), layer_data_map);
-        my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
-        layer_init_instance_dispatch_table(my_data->instance_dispatch_table, wrapped_inst);
+    if (!strcmp(funcName, "vkGetInstanceProcAddr"))
         return (PFN_vkVoidFunction) vkGetInstanceProcAddr;
-    }
-    my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
+    if (!strcmp(funcName, "vkGetDeviceProcAddr"))
+        return (PFN_vkVoidFunction) vkGetDeviceProcAddr;
     if (!strcmp(funcName, "vkDestroyInstance"))
         return (PFN_vkVoidFunction) vkDestroyInstance;
     if (!strcmp(funcName, "vkCreateInstance"))
         return (PFN_vkVoidFunction) vkCreateInstance;
     if (!strcmp(funcName, "vkGetPhysicalDeviceMemoryProperties"))
         return (PFN_vkVoidFunction) vkGetPhysicalDeviceMemoryProperties;
+    if (!strcmp(funcName, "vkCreateDevice"))
+        return (PFN_vkVoidFunction) vkCreateDevice;
     if (!strcmp(funcName, "vkEnumerateInstanceLayerProperties"))
         return (PFN_vkVoidFunction) vkEnumerateInstanceLayerProperties;
     if (!strcmp(funcName, "vkEnumerateInstanceExtensionProperties"))
@@ -3386,14 +3408,16 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(
     if (!strcmp(funcName, "vkEnumerateDeviceExtensionProperties"))
         return (PFN_vkVoidFunction) vkEnumerateDeviceExtensionProperties;
 
+    if (instance == NULL) return NULL;
+
+    layer_data *my_data;
+    my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
+
     fptr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);
-    if (fptr)
-        return fptr;
+    if (fptr) return fptr;
 
-    {
-        VkLayerInstanceDispatchTable* pTable = my_data->instance_dispatch_table;
-        if (pTable->GetInstanceProcAddr == NULL)
-            return NULL;
-        return pTable->GetInstanceProcAddr(instance, funcName);
-    }
+    VkLayerInstanceDispatchTable* pTable = my_data->instance_dispatch_table;
+    if (pTable->GetInstanceProcAddr == NULL)
+        return NULL;
+    return pTable->GetInstanceProcAddr(instance, funcName);
 }
index c5d9d1b..3bbea8c 100644 (file)
@@ -80,28 +80,22 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL multi1CreateGraphicsPipelines(
 
 VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL multi1GetDeviceProcAddr(VkDevice device, const char* pName)
 {
-
-    if (device == NULL)
-        return NULL;
-
-    /* loader uses this to force layer initialization; device object is wrapped */
-    if (!strcmp(pName, "multi1GetDeviceProcAddr") || !strcmp(pName, "vkGetDeviceProcAddr")) {
-        initDeviceTable(multi1_device_table_map, (const VkBaseLayerObject *) device);
+    if (!strcmp(pName, "multi1GetDeviceProcAddr") || !strcmp(pName, "vkGetDeviceProcAddr"))
         return (PFN_vkVoidFunction) multi1GetDeviceProcAddr;
-    }
-
     if (!strcmp("vkDestroyDevice", pName))
         return (PFN_vkVoidFunction) multi1DestroyDevice;
     if (!strcmp("vkCreateSampler", pName))
         return (PFN_vkVoidFunction) multi1CreateSampler;
     if (!strcmp("vkCreateGraphicsPipelines", pName))
         return (PFN_vkVoidFunction) multi1CreateGraphicsPipelines;
-    else {
-        VkLayerDispatchTable *pTable = get_dispatch_table(multi1_device_table_map, device);
-        if (pTable->GetDeviceProcAddr == NULL)
-            return NULL;
-        return pTable->GetDeviceProcAddr(device, pName);
-    }
+
+    if (device == NULL)
+        return NULL;
+
+    VkLayerDispatchTable *pTable = get_dispatch_table(multi1_device_table_map, device);
+    if (pTable->GetDeviceProcAddr == NULL)
+        return NULL;
+    return pTable->GetDeviceProcAddr(device, pName);
 }
 
 
@@ -154,15 +148,8 @@ VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL multi2DestroyInstance(VkInstance inst
 
 VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL multi2GetInstanceProcAddr(VkInstance inst, const char* pName)
 {
-    if (inst == NULL)
-        return NULL;
-
-    /* loader uses this to force layer initialization; device object is wrapped */
-    if (!strcmp(pName, "multi2GetInstanceProcAddr") || !strcmp(pName, "vkGetInstanceProcAddr")) {
-        initInstanceTable(multi2_instance_table_map, (const VkBaseLayerObject *) inst);
+    if (!strcmp(pName, "multi2GetInstanceProcAddr") || !strcmp(pName, "vkGetInstanceProcAddr"))
         return (PFN_vkVoidFunction) multi2GetInstanceProcAddr;
-    }
-
     if (!strcmp("vkEnumeratePhysicalDevices", pName))
         return (PFN_vkVoidFunction) multi2EnumeratePhysicalDevices;
     if (!strcmp("GetPhysicalDeviceProperties", pName))
@@ -171,12 +158,14 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL multi2GetInstanceProcAd
         return (PFN_vkVoidFunction) multi2GetPhysicalDeviceFeatures;
     if (!strcmp("vkDestroyInstance", pName))
         return (PFN_vkVoidFunction) multi2DestroyInstance;
-    else {
-        VkLayerInstanceDispatchTable *pTable = get_dispatch_table(multi2_instance_table_map, inst);
-        if (pTable->GetInstanceProcAddr == NULL)
-            return NULL;
-        return pTable->GetInstanceProcAddr(inst, pName);
-    }
+
+    if (inst == NULL)
+        return NULL;
+
+    VkLayerInstanceDispatchTable *pTable = get_dispatch_table(multi2_instance_table_map, inst);
+    if (pTable->GetInstanceProcAddr == NULL)
+        return NULL;
+    return pTable->GetInstanceProcAddr(inst, pName);
 }
 
 #ifdef __cplusplus
index de44f0e..4622c18 100644 (file)
@@ -29,6 +29,7 @@
 #include "vulkan/vk_layer.h"
 #include "vk_layer_extension_utils.h"
 #include "vk_enum_string_helper.h"
+#include "vk_layer_table.h"
 
 // Object Tracker ERROR codes
 typedef enum _OBJECT_TRACK_ERROR
@@ -689,22 +690,38 @@ explicit_CreateInstance(
     const VkAllocationCallbacks *pAllocator,
     VkInstance                  *pInstance)
 {
+    VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
 
-    VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(object_tracker_instance_table_map, *pInstance);
-    VkResult result = pInstanceTable->CreateInstance(pCreateInfo, pAllocator, pInstance);
+    assert(chain_info->u.pLayerInfo);
+    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
+    PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance) fpGetInstanceProcAddr(NULL, "vkCreateInstance");
+    if (fpCreateInstance == NULL) {
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
 
-    if (result == VK_SUCCESS) {
-        layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
-        my_data->report_data = debug_report_create_instance(
-                                   pInstanceTable,
-                                   *pInstance,
-                                   pCreateInfo->enabledExtensionCount,
-                                   pCreateInfo->ppEnabledExtensionNames);
-        createInstanceRegisterExtensions(pCreateInfo, *pInstance);
-
-        initObjectTracker(my_data, pAllocator);
-        create_instance(*pInstance, *pInstance, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT);
+    // Advance the link info for the next element on the chain
+    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
+
+    VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
+    if (result != VK_SUCCESS) {
+        return result;
     }
+
+    layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
+    initInstanceTable(*pInstance, fpGetInstanceProcAddr, object_tracker_instance_table_map);
+    VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(object_tracker_instance_table_map, *pInstance);
+
+    my_data->report_data = debug_report_create_instance(
+                               pInstanceTable,
+                               *pInstance,
+                               pCreateInfo->enabledExtensionCount,
+                               pCreateInfo->ppEnabledExtensionNames);
+
+    initObjectTracker(my_data, pAllocator);
+    createInstanceRegisterExtensions(pCreateInfo, *pInstance);
+
+    create_instance(*pInstance, *pInstance, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT);
+
     return result;
 }
 
@@ -730,16 +747,36 @@ explicit_CreateDevice(
     VkDevice                 *pDevice)
 {
     loader_platform_thread_lock_mutex(&objLock);
-    VkLayerDispatchTable *pDeviceTable = get_dispatch_table(object_tracker_device_table_map, *pDevice);
-    VkResult result = pDeviceTable->CreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
-    if (result == VK_SUCCESS) {
-        layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(gpu), layer_data_map);
-        layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
-        my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
-        create_device(*pDevice, *pDevice, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT);
-        createDeviceRegisterExtensions(pCreateInfo, *pDevice);
+    VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
+
+    assert(chain_info->u.pLayerInfo);
+    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
+    PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
+    PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice) fpGetInstanceProcAddr(NULL, "vkCreateDevice");
+    if (fpCreateDevice == NULL) {
+        loader_platform_thread_unlock_mutex(&objLock);
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
+    // Advance the link info for the next element on the chain
+    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
+
+    VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
+    if (result != VK_SUCCESS) {
+        loader_platform_thread_unlock_mutex(&objLock);
+        return result;
     }
 
+    layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(gpu), layer_data_map);
+    layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
+    my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
+
+    initDeviceTable(*pDevice, fpGetDeviceProcAddr, object_tracker_device_table_map);
+
+    createDeviceRegisterExtensions(pCreateInfo, *pDevice);
+
+    create_device(*pDevice, *pDevice, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT);
+
     loader_platform_thread_unlock_mutex(&objLock);
     return result;
 }
index c351837..f63562d 100644 (file)
@@ -1760,18 +1760,34 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(
     const VkAllocationCallbacks* pAllocator,
     VkInstance* pInstance)
 {
-    VkLayerInstanceDispatchTable *pTable = get_dispatch_table(pc_instance_table_map, *pInstance);
-    VkResult result = pTable->CreateInstance(pCreateInfo, pAllocator, pInstance);
+    VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
 
-    if (result == VK_SUCCESS) {
-        layer_data *data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
-        data->report_data = debug_report_create_instance(pTable, *pInstance, pCreateInfo->enabledExtensionCount,
-            pCreateInfo->ppEnabledExtensionNames);
-
-        InitParamChecker(data, pAllocator);
+    assert(chain_info->u.pLayerInfo);
+    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
+    PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance) fpGetInstanceProcAddr(NULL, "vkCreateInstance");
+    if (fpCreateInstance == NULL) {
+        return VK_ERROR_INITIALIZATION_FAILED;
     }
 
+    // Advance the link info for the next element on the chain
+    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
+
+    VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
+    if (result != VK_SUCCESS)
         return result;
+
+    layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
+    VkLayerInstanceDispatchTable *pTable = initInstanceTable(*pInstance, fpGetInstanceProcAddr, pc_instance_table_map);
+
+    my_data->report_data = debug_report_create_instance(
+                               pTable,
+                               *pInstance,
+                               pCreateInfo->enabledExtensionCount,
+                               pCreateInfo->ppEnabledExtensionNames);
+
+    InitParamChecker(my_data, pAllocator);
+
+    return result;
 }
 
 VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(
@@ -2035,21 +2051,32 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(
     VkDevice* pDevice)
 {
     /*
-     * NOTE: The loader fills in the ICD's device object in *pDevice.
-     * Use that object to get the dispatch table.
-     *
      * NOTE: We do not validate physicalDevice or any dispatchable
      * object as the first parameter. We couldn't get here if it was wrong!
      */
-    VkLayerDispatchTable *pTable = get_dispatch_table(pc_device_table_map, *pDevice);
-    VkResult result = pTable->CreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
-    if(result == VK_SUCCESS)
-    {
-        layer_data *instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
-        layer_data *device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
-        device_data->report_data = layer_debug_report_create_device(instance_data->report_data, *pDevice);
+    VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
+
+    assert(chain_info->u.pLayerInfo);
+    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
+    PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
+    PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice) fpGetInstanceProcAddr(NULL, "vkCreateDevice");
+    if (fpCreateDevice == NULL) {
+        return VK_ERROR_INITIALIZATION_FAILED;
     }
 
+    // Advance the link info for the next element on the chain
+    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
+
+    VkResult result = fpCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
+    if (result != VK_SUCCESS) {
+        return result;
+    }
+
+    layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
+    layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
+    my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
+    initDeviceTable(*pDevice, fpGetDeviceProcAddr, pc_device_table_map);
+
     return result;
 }
 
@@ -6437,18 +6464,8 @@ VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdExecuteCommands(
 
 VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char* funcName)
 {
-    if (device == NULL) {
-        return NULL;
-    }
-
-    /* loader uses this to force layer initialization; device object is wrapped */
-    if (!strcmp(funcName, "vkGetDeviceProcAddr")) {
-        initDeviceTable(pc_device_table_map, (const VkBaseLayerObject *) device);
+    if (!strcmp(funcName, "vkGetDeviceProcAddr"))
         return (PFN_vkVoidFunction) vkGetDeviceProcAddr;
-    }
-
-    if (!strcmp(funcName, "vkCreateDevice"))
-        return (PFN_vkVoidFunction) vkCreateDevice;
     if (!strcmp(funcName, "vkDestroyDevice"))
         return (PFN_vkVoidFunction) vkDestroyDevice;
     if (!strcmp(funcName, "vkGetDeviceQueue"))
@@ -6608,29 +6625,25 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkD
     if (!strcmp(funcName, "vkCmdNextSubpass"))
         return (PFN_vkVoidFunction) vkCmdNextSubpass;
 
-    {
-        if (get_dispatch_table(pc_device_table_map, device)->GetDeviceProcAddr == NULL)
-            return NULL;
-        return get_dispatch_table(pc_device_table_map, device)->GetDeviceProcAddr(device, funcName);
+    if (device == NULL) {
+        return NULL;
     }
+
+    if (get_dispatch_table(pc_device_table_map, device)->GetDeviceProcAddr == NULL)
+        return NULL;
+    return get_dispatch_table(pc_device_table_map, device)->GetDeviceProcAddr(device, funcName);
 }
 
 VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char* funcName)
 {
-    if (instance == NULL) {
-        return NULL;
-    }
-
-    /* loader uses this to force layer initialization; instance object is wrapped */
-    if (!strcmp(funcName, "vkGetInstanceProcAddr")) {
-        initInstanceTable(pc_instance_table_map, (const VkBaseLayerObject *) instance);
+    if (!strcmp(funcName, "vkGetInstanceProcAddr"))
         return (PFN_vkVoidFunction) vkGetInstanceProcAddr;
-    }
-
     if (!strcmp(funcName, "vkCreateInstance"))
         return (PFN_vkVoidFunction) vkCreateInstance;
     if (!strcmp(funcName, "vkDestroyInstance"))
         return (PFN_vkVoidFunction) vkDestroyInstance;
+    if (!strcmp(funcName, "vkCreateDevice"))
+        return (PFN_vkVoidFunction) vkCreateDevice;
     if (!strcmp(funcName, "vkEnumeratePhysicalDevices"))
         return (PFN_vkVoidFunction) vkEnumeratePhysicalDevices;
     if (!strcmp(funcName, "vkGetPhysicalDeviceProperties"))
@@ -6648,14 +6661,16 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(V
     if (!strcmp(funcName, "vkEnumerateDeviceExtensionProperties"))
         return (PFN_vkVoidFunction) vkEnumerateDeviceExtensionProperties;
 
+    if (instance == NULL) {
+        return NULL;
+    }
+
     layer_data *data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
     PFN_vkVoidFunction fptr = debug_report_get_instance_proc_addr(data->report_data, funcName);
     if(fptr)
         return fptr;
 
-    {
-        if (get_dispatch_table(pc_instance_table_map, instance)->GetInstanceProcAddr == NULL)
-            return NULL;
-        return get_dispatch_table(pc_instance_table_map, instance)->GetInstanceProcAddr(instance, funcName);
-    }
+    if (get_dispatch_table(pc_instance_table_map, instance)->GetInstanceProcAddr == NULL)
+        return NULL;
+    return get_dispatch_table(pc_instance_table_map, instance)->GetInstanceProcAddr(instance, funcName);
 }
index 521aedc..3231289 100644 (file)
@@ -406,21 +406,36 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(
     const VkAllocationCallbacks* pAllocator,
     VkDevice                 *pDevice)
 {
-    VkLayerDispatchTable *pDisp  = get_dispatch_table(screenshot_device_table_map, *pDevice);
-    VkResult result = pDisp->CreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
-
-    if (result == VK_SUCCESS) {
-        init_screenshot();
-        createDeviceRegisterExtensions(pCreateInfo, *pDevice);
-        // Create a mapping from a device to a physicalDevice
-        if (deviceMap[*pDevice] == NULL)
-        {
-            DeviceMapStruct *deviceMapElem = new DeviceMapStruct;
-            deviceMap[*pDevice] = deviceMapElem;
-        }
-        deviceMap[*pDevice]->physicalDevice = gpu;
+    VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
+
+    assert(chain_info->u.pLayerInfo);
+    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
+    PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
+    PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice) fpGetInstanceProcAddr(NULL, "vkCreateDevice");
+    if (fpCreateDevice == NULL) {
+        return VK_ERROR_INITIALIZATION_FAILED;
     }
 
+    // Advance the link info for the next element on the chain
+    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
+
+    VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
+    if (result != VK_SUCCESS) {
+        return result;
+    }
+
+    initDeviceTable(*pDevice, fpGetDeviceProcAddr, screenshot_device_table_map);
+
+    init_screenshot();
+    createDeviceRegisterExtensions(pCreateInfo, *pDevice);
+    // Create a mapping from a device to a physicalDevice
+    if (deviceMap[*pDevice] == NULL)
+    {
+        DeviceMapStruct *deviceMapElem = new DeviceMapStruct;
+        deviceMap[*pDevice] = deviceMapElem;
+    }
+    deviceMap[*pDevice]->physicalDevice = gpu;
+
     return result;
 }
 
@@ -743,17 +758,9 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(
     VkDevice         dev,
     const char       *funcName)
 {
-    if (dev == NULL) {
-        return NULL;
-    }
-
-    /* loader uses this to force layer initialization; device object is wrapped */
     if (!strcmp(funcName, "vkGetDeviceProcAddr")) {
-        initDeviceTable(screenshot_device_table_map, (const VkBaseLayerObject *) dev);
         return (PFN_vkVoidFunction)vkGetDeviceProcAddr;
     }
-    if (!strcmp(funcName, "vkCreateDevice"))
-        return (PFN_vkVoidFunction) vkCreateDevice;
 
     if (!strcmp(funcName, "vkGetDeviceQueue"))
         return (PFN_vkVoidFunction) vkGetDeviceQueue;
@@ -761,6 +768,10 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(
     if (!strcmp(funcName, "vkCreateCommandPool"))
         return (PFN_vkVoidFunction) vkCreateCommandPool;
 
+    if (dev == NULL) {
+        return NULL;
+    }
+
     VkLayerDispatchTable *pDisp =  get_dispatch_table(screenshot_device_table_map, dev);
     if (deviceExtMap.size() != 0 && deviceExtMap[pDisp].wsi_enabled)
     {
@@ -780,21 +791,19 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(
 
 VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char* funcName)
 {
-    if (instance == VK_NULL_HANDLE) {
-        return NULL;
-    }
-
-    /* loader uses this to force layer initialization; instance object is wrapped */
-    if (!strcmp("vkGetInstanceProcAddr", funcName)) {
-        initInstanceTable((const VkBaseLayerObject *) instance);
+    if (!strcmp("vkGetInstanceProcAddr", funcName))
         return (PFN_vkVoidFunction) vkGetInstanceProcAddr;
-    }
-
+    if (!strcmp(funcName, "vkCreateDevice"))
+        return (PFN_vkVoidFunction) vkCreateDevice;
     if (!strcmp(funcName, "vkEnumeratePhysicalDevices"))
                return (PFN_vkVoidFunction)vkEnumeratePhysicalDevices;
     if (!strcmp(funcName, "vkEnumerateDeviceExtensionProperties"))
                return (PFN_vkVoidFunction)vkEnumerateDeviceExtensionProperties;
 
+    if (instance == VK_NULL_HANDLE) {
+        return NULL;
+    }
+
     VkLayerInstanceDispatchTable* pTable = instance_dispatch_table(instance);
     if (pTable->GetInstanceProcAddr == NULL)
         return NULL;
index d9e0a09..051d14f 100644 (file)
@@ -286,22 +286,37 @@ static const char *sharingModeStr(VkSharingMode value)
 
 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance)
 {
-    layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
-    // Call down the call chain:
-    VkLayerInstanceDispatchTable* pTable = my_data->instance_dispatch_table;
-    VkResult result = pTable->CreateInstance(pCreateInfo, pAllocator, pInstance);
-    if (result == VK_SUCCESS) {
-        // Since it succeeded, do layer-specific work:
-        layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
-        my_data->report_data = debug_report_create_instance(
-                                   pTable,
-                                   *pInstance,
-                                   pCreateInfo->enabledExtensionCount,
-                                   pCreateInfo->ppEnabledExtensionNames);
-        // Call the following function after my_data is initialized:
-        createInstanceRegisterExtensions(pCreateInfo, *pInstance);
-        initSwapchain(my_data, pAllocator);
+    VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
+
+    assert(chain_info->u.pLayerInfo);
+    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
+    PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance) fpGetInstanceProcAddr(NULL, "vkCreateInstance");
+    if (fpCreateInstance == NULL) {
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
+    // Advance the link info for the next element on the chain
+    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
+
+    VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
+    if (result != VK_SUCCESS) {
+        return result;
     }
+
+    layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
+    my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
+    layer_init_instance_dispatch_table(*pInstance, my_data->instance_dispatch_table, fpGetInstanceProcAddr);
+
+    my_data->report_data = debug_report_create_instance(
+                               my_data->instance_dispatch_table,
+                               *pInstance,
+                               pCreateInfo->enabledExtensionCount,
+                               pCreateInfo->ppEnabledExtensionNames);
+
+    // Call the following function after my_data is initialized:
+    createInstanceRegisterExtensions(pCreateInfo, *pInstance);
+    initSwapchain(my_data, pAllocator);
+
     return result;
 }
 
@@ -874,22 +889,34 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDevices(VkInst
 
 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice)
 {
-    VkResult result = VK_SUCCESS;
-    VkBool32 skipCall = VK_FALSE;
-    layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
+    VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
 
-    if (VK_FALSE == skipCall) {
-        layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
-        // Call down the call chain:
-        result = my_device_data->device_dispatch_table->CreateDevice(
-                physicalDevice, pCreateInfo, pAllocator, pDevice);
-        if (result == VK_SUCCESS) {
-            // Since it succeeded, do layer-specific work:
-            layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
-            my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
-            createDeviceRegisterExtensions(physicalDevice, pCreateInfo, *pDevice);
-        }
+    assert(chain_info->u.pLayerInfo);
+    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
+    PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
+    PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice) fpGetInstanceProcAddr(NULL, "vkCreateDevice");
+    if (fpCreateDevice == NULL) {
+        return VK_ERROR_INITIALIZATION_FAILED;
     }
+
+    // Advance the link info for the next element on the chain
+    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
+
+    VkResult result = fpCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
+    if (result != VK_SUCCESS) {
+        return result;
+    }
+
+    layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
+    layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
+
+    // Setup device dispatch table
+    my_device_data->device_dispatch_table = new VkLayerDispatchTable;
+    layer_init_device_dispatch_table(*pDevice, my_device_data->device_dispatch_table, fpGetDeviceProcAddr);
+
+    my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
+    createDeviceRegisterExtensions(physicalDevice, pCreateInfo, *pDevice);
+
     return result;
 }
 
@@ -1861,41 +1888,6 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkQueuePresentKHR(
     return VK_ERROR_VALIDATION_FAILED_EXT;
 }
 
-static inline PFN_vkVoidFunction layer_intercept_proc(const char *name)
-{
-    if (!name || name[0] != 'v' || name[1] != 'k')
-        return NULL;
-
-    name += 2;
-    if (!strcmp(name, "CreateInstance"))
-        return (PFN_vkVoidFunction) vkCreateInstance;
-    if (!strcmp(name, "DestroyInstance"))
-        return (PFN_vkVoidFunction) vkDestroyInstance;
-    if (!strcmp(name, "EnumeratePhysicalDevices"))
-        return (PFN_vkVoidFunction) vkEnumeratePhysicalDevices;
-    if (!strcmp(name, "CreateDevice"))
-        return (PFN_vkVoidFunction) vkCreateDevice;
-    if (!strcmp(name, "DestroyDevice"))
-        return (PFN_vkVoidFunction) vkDestroyDevice;
-
-    return NULL;
-}
-static inline PFN_vkVoidFunction layer_intercept_instance_proc(const char *name)
-{
-    if (!name || name[0] != 'v' || name[1] != 'k')
-        return NULL;
-
-    name += 2;
-    if (!strcmp(name, "CreateInstance"))
-        return (PFN_vkVoidFunction) vkCreateInstance;
-    if (!strcmp(name, "DestroyInstance"))
-        return (PFN_vkVoidFunction) vkDestroyInstance;
-    if (!strcmp(name, "EnumeratePhysicalDevices"))
-        return (PFN_vkVoidFunction) vkEnumeratePhysicalDevices;
-
-    return NULL;
-}
-
 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugReportCallbackEXT(
         VkInstance                                      instance,
         const VkDebugReportCallbackCreateInfoEXT*       pCreateInfo,
@@ -1933,24 +1925,16 @@ VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDebugReportMessageEXT(
 
 VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char* funcName)
 {
-    PFN_vkVoidFunction addr;
+    if (!strcmp("vkGetDeviceProcAddr", funcName))
+        return (PFN_vkVoidFunction) vkGetDeviceProcAddr;
+    if (!strcmp(funcName, "vkDestroyDevice"))
+        return (PFN_vkVoidFunction) vkDestroyDevice;
+
     if (device == VK_NULL_HANDLE) {
         return NULL;
     }
 
     layer_data *my_data;
-    /* loader uses this to force layer initialization; device object is wrapped */
-    if (!strcmp("vkGetDeviceProcAddr", funcName)) {
-        VkBaseLayerObject* wrapped_dev = (VkBaseLayerObject*) device;
-        my_data = get_my_data_ptr(get_dispatch_key(wrapped_dev->baseObject), layer_data_map);
-        my_data->device_dispatch_table = new VkLayerDispatchTable;
-        layer_initialize_dispatch_table(my_data->device_dispatch_table, wrapped_dev);
-        return (PFN_vkVoidFunction) vkGetDeviceProcAddr;
-    }
-
-    addr = layer_intercept_proc(funcName);
-    if (addr)
-        return addr;
 
     my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
     VkLayerDispatchTable *pDisp =  my_data->device_dispatch_table;
@@ -1968,39 +1952,36 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkD
         if (!strcmp("vkQueuePresentKHR", funcName))
             return reinterpret_cast<PFN_vkVoidFunction>(vkQueuePresentKHR);
     }
-    {
-        if (pDisp->GetDeviceProcAddr == NULL)
-            return NULL;
-        return pDisp->GetDeviceProcAddr(device, funcName);
-    }
+
+    if (pDisp->GetDeviceProcAddr == NULL)
+        return NULL;
+    return pDisp->GetDeviceProcAddr(device, funcName);
 }
 
 VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char* funcName)
 {
-    PFN_vkVoidFunction addr;
-    if (instance == VK_NULL_HANDLE) {
-        return NULL;
-    }
-
-    layer_data *my_data;
-    /* loader uses this to force layer initialization; instance object is wrapped */
-    if (!strcmp("vkGetInstanceProcAddr", funcName)) {
-        VkBaseLayerObject* wrapped_inst = (VkBaseLayerObject*) instance;
-        my_data = get_my_data_ptr(get_dispatch_key(wrapped_inst->baseObject), layer_data_map);
-        my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
-        layer_init_instance_dispatch_table(my_data->instance_dispatch_table, wrapped_inst);
+    if (!strcmp("vkGetInstanceProcAddr", funcName))
         return (PFN_vkVoidFunction) vkGetInstanceProcAddr;
-    }
-
+    if (!strcmp(funcName, "vkCreateInstance"))
+        return (PFN_vkVoidFunction) vkCreateInstance;
+    if (!strcmp(funcName, "vkDestroyInstance"))
+        return (PFN_vkVoidFunction) vkDestroyInstance;
+    if (!strcmp(funcName, "vkCreateDevice"))
+        return (PFN_vkVoidFunction) vkCreateDevice;
+    if (!strcmp(funcName, "vkEnumeratePhysicalDevices"))
+        return (PFN_vkVoidFunction) vkEnumeratePhysicalDevices;
     if (!strcmp(funcName, "vkEnumerateInstanceLayerProperties"))
         return (PFN_vkVoidFunction) vkEnumerateInstanceLayerProperties;
     if (!strcmp(funcName, "vkEnumerateInstanceExtensionProperties"))
         return (PFN_vkVoidFunction) vkEnumerateInstanceExtensionProperties;
 
-    addr = layer_intercept_instance_proc(funcName);
-    if (addr)
-        return addr;
+    if (instance == VK_NULL_HANDLE) {
+        return NULL;
+    }
+
+    PFN_vkVoidFunction addr;
 
+    layer_data *my_data;
     my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
     VkLayerInstanceDispatchTable* pTable = my_data->instance_dispatch_table;
     addr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);
index 02e6699..8d344a0 100644 (file)
@@ -141,13 +141,27 @@ explicit_CreateInstance(
     const VkAllocationCallbacks *pAllocator,
     VkInstance                  *pInstance)
 {
+    VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
 
-    VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(unique_objects_instance_table_map, *pInstance);
-    VkResult result = pInstanceTable->CreateInstance(pCreateInfo, pAllocator, pInstance);
+    assert(chain_info->u.pLayerInfo);
+    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
+    PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance) fpGetInstanceProcAddr(NULL, "vkCreateInstance");
+    if (fpCreateInstance == NULL) {
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
+    // Advance the link info for the next element on the chain
+    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
 
-    if (result == VK_SUCCESS) {
-        createInstanceRegisterExtensions(pCreateInfo, *pInstance);
+    VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
+    if (result != VK_SUCCESS) {
+        return result;
     }
+
+    initInstanceTable(*pInstance, fpGetInstanceProcAddr, unique_objects_instance_table_map);
+
+    createInstanceRegisterExtensions(pCreateInfo, *pInstance);
+
     return result;
 }
 
@@ -176,11 +190,29 @@ explicit_CreateDevice(
     const VkAllocationCallbacks   *pAllocator,
     VkDevice                 *pDevice)
 {
-    VkLayerDispatchTable *pDeviceTable = get_dispatch_table(unique_objects_device_table_map, *pDevice);
-    VkResult result = pDeviceTable->CreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
-    if (result == VK_SUCCESS) {
-        createDeviceRegisterExtensions(pCreateInfo, *pDevice);
+    VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
+
+    assert(chain_info->u.pLayerInfo);
+    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
+    PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
+    PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice) fpGetInstanceProcAddr(NULL, "vkCreateDevice");
+    if (fpCreateDevice == NULL) {
+        return VK_ERROR_INITIALIZATION_FAILED;
     }
+
+    // Advance the link info for the next element on the chain
+    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
+
+    VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
+    if (result != VK_SUCCESS) {
+        return result;
+    }
+
+    // Setup layer's device dispatch table
+    initDeviceTable(*pDevice, fpGetDeviceProcAddr, unique_objects_device_table_map);
+
+    createDeviceRegisterExtensions(pCreateInfo, *pDevice);
+
     return result;
 }
 
index 93d2fbf..b06fb31 100644 (file)
@@ -100,9 +100,9 @@ VkLayerDispatchTable *get_dispatch_table(device_table_map &map, void* object)
     device_table_map::const_iterator it = map.find((void *) key);
 #if DISPATCH_MAP_DEBUG
     if (it != map.end()) {
-        fprintf(stderr, "instance_dispatch_table: map: %p, object: %p, key: %p, table: %p\n", &tableInstanceMap, object, key, it->second);
+        fprintf(stderr, "device_dispatch_table: map: %p, object: %p, key: %p, table: %p\n", &tableInstanceMap, object, key, it->second);
     } else {
-        fprintf(stderr, "instance_dispatch_table: map: %p, object: %p, key: %p, table: UNKNOWN\n", &tableInstanceMap, object, key);
+        fprintf(stderr, "device_dispatch_table: map: %p, object: %p, key: %p, table: UNKNOWN\n", &tableInstanceMap, object, key);
     }
 #endif
     assert(it != map.end() && "Not able to find device dispatch entry");
@@ -125,20 +125,22 @@ VkLayerInstanceDispatchTable *get_dispatch_table(instance_table_map &map, void*
     return it->second;
 }
 
-VkLayerInstanceCreateInfo *get_chain_info(const VkInstanceCreateInfo *pCreateInfo)
+VkLayerInstanceCreateInfo *get_chain_info(const VkInstanceCreateInfo *pCreateInfo, VkLayerFunction func)
 {
     VkLayerInstanceCreateInfo *chain_info = (VkLayerInstanceCreateInfo *) pCreateInfo->pNext;
-    while (chain_info && chain_info->sType != VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO) {
+    while (chain_info && !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO
+           && chain_info->function == func)) {
         chain_info = (VkLayerInstanceCreateInfo *) chain_info->pNext;
     }
     assert(chain_info != NULL);
     return chain_info;
 }
 
-VkLayerDeviceCreateInfo *get_chain_info(const VkDeviceCreateInfo *pCreateInfo)
+VkLayerDeviceCreateInfo *get_chain_info(const VkDeviceCreateInfo *pCreateInfo, VkLayerFunction func)
 {
     VkLayerDeviceCreateInfo *chain_info = (VkLayerDeviceCreateInfo *) pCreateInfo->pNext;
-    while (chain_info && chain_info->sType != VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO) {
+    while (chain_info && !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO
+           && chain_info->function == func)) {
         chain_info = (VkLayerDeviceCreateInfo *) chain_info->pNext;
     }
     assert(chain_info != NULL);
@@ -152,67 +154,64 @@ VkLayerDeviceCreateInfo *get_chain_info(const VkDeviceCreateInfo *pCreateInfo)
  *    Device -> CommandBuffer or Queue
  * If use the object themselves as key to map then implies Create entrypoints have to be intercepted
  * and a new key inserted into map */
-VkLayerInstanceDispatchTable * initInstanceTable(instance_table_map &map, const VkBaseLayerObject *instancew)
+VkLayerInstanceDispatchTable * initInstanceTable(VkInstance instance, const PFN_vkGetInstanceProcAddr gpa, instance_table_map &map)
 {
     VkLayerInstanceDispatchTable *pTable;
-    assert(instancew);
-    VkLayerInstanceDispatchTable **ppDisp = (VkLayerInstanceDispatchTable **) instancew->baseObject;
+    dispatch_key key = get_dispatch_key(instance);
+    instance_table_map::const_iterator it = map.find((void *) key);
 
-    std::unordered_map<void *, VkLayerInstanceDispatchTable *>::const_iterator it = map.find((void *) *ppDisp);
     if (it == map.end())
     {
         pTable =  new VkLayerInstanceDispatchTable;
-        map[(void *) *ppDisp] = pTable;
+        map[(void *) key] = pTable;
 #if DISPATCH_MAP_DEBUG
-        fprintf(stderr, "New, Instance: map: %p, base object: %p, key: %p, table: %p\n", &map, instancew, *ppDisp, pTable);
+        fprintf(stderr, "New, Instance: map: %p, key: %p, table: %p\n", &map, key, pTable);
 #endif
     } else
     {
 #if DISPATCH_MAP_DEBUG
-        fprintf(stderr, "Instance: map: %p, base object: %p, key: %p, table: %p\n", &map, instancew, *ppDisp, it->second);
+        fprintf(stderr, "Instance: map: %p, key: %p, table: %p\n", &map, key, it->second);
 #endif
         return it->second;
     }
 
-    layer_init_instance_dispatch_table(pTable, instancew);
+    layer_init_instance_dispatch_table(instance, pTable, gpa);
 
     return pTable;
 }
 
-VkLayerInstanceDispatchTable * initInstanceTable(const VkBaseLayerObject *instancew)
+VkLayerInstanceDispatchTable * initInstanceTable(VkInstance instance, const PFN_vkGetInstanceProcAddr gpa)
 {
-    return initInstanceTable(tableInstanceMap, instancew);
+    return initInstanceTable(instance, gpa, tableInstanceMap);
 }
 
-VkLayerDispatchTable * initDeviceTable(device_table_map &map, const VkBaseLayerObject *devw)
+VkLayerDispatchTable * initDeviceTable(VkDevice device, const PFN_vkGetDeviceProcAddr gpa, device_table_map &map)
 {
-    VkLayerDispatchTable *layer_device_table = NULL;
-    assert(devw);
-    VkLayerDispatchTable **ppDisp = (VkLayerDispatchTable **) (devw->baseObject);
-    VkLayerDispatchTable *base_device_table = *ppDisp;
+    VkLayerDispatchTable *pTable;
+    dispatch_key key = get_dispatch_key(device);
+    device_table_map::const_iterator it = map.find((void *) key);
 
-    std::unordered_map<void *, VkLayerDispatchTable *>::const_iterator it = map.find((void *) base_device_table);
     if (it == map.end())
     {
-        layer_device_table =  new VkLayerDispatchTable;
-        map[(void *) base_device_table] = layer_device_table;
+        pTable =  new VkLayerDispatchTable;
+        map[(void *) key] = pTable;
 #if DISPATCH_MAP_DEBUG
-        fprintf(stderr, "New, Device: map: %p, base object: %p, key: %p, table: %p\n", &map, devw, *ppDisp, layer_device_table);
+        fprintf(stderr, "New, Device: map: %p, key: %p, table: %p\n", &map, key, pTable);
 #endif
     } else
     {
 #if DISPATCH_MAP_DEBUG
-        fprintf(stderr, "Device: map: %p, base object: %p, key: %p, table: %p\n", &map, devw, *ppDisp, it->second);
+        fprintf(stderr, "Device: map: %p, key: %p, table: %p\n", &map, key, it->second);
 #endif
         return it->second;
     }
 
-    layer_initialize_dispatch_table(layer_device_table, devw);
+    layer_init_device_dispatch_table(device, pTable, gpa);
 
-    return layer_device_table;
+    return pTable;
 }
 
-VkLayerDispatchTable * initDeviceTable(const VkBaseLayerObject *devw)
+VkLayerDispatchTable * initDeviceTable(VkDevice device, const PFN_vkGetDeviceProcAddr gpa)
 {
-    return initDeviceTable(tableMap, devw);
+    return initDeviceTable(device, gpa, tableMap);
 }
index 04ea266..0011c85 100644 (file)
 
 typedef std::unordered_map<void *, VkLayerDispatchTable *> device_table_map;
 typedef std::unordered_map<void *, VkLayerInstanceDispatchTable *> instance_table_map;
-VkLayerDispatchTable * initDeviceTable(const VkBaseLayerObject *devw);
-VkLayerDispatchTable * initDeviceTable(device_table_map &map, const VkBaseLayerObject *devw);
-VkLayerInstanceDispatchTable * initInstanceTable(const VkBaseLayerObject *instancew);
-VkLayerInstanceDispatchTable * initInstanceTable(instance_table_map &map, const VkBaseLayerObject *instancew);
+VkLayerDispatchTable * initDeviceTable(VkDevice device, const PFN_vkGetDeviceProcAddr gpa, device_table_map &map);
+VkLayerDispatchTable * initDeviceTable(VkDevice device, const PFN_vkGetDeviceProcAddr gpa);
+VkLayerInstanceDispatchTable * initInstanceTable(VkInstance instance, const PFN_vkGetInstanceProcAddr gpa, instance_table_map &map);
+VkLayerInstanceDispatchTable * initInstanceTable(VkInstance instance, const PFN_vkGetInstanceProcAddr gpa);
+
 
 typedef void *dispatch_key;
 
@@ -49,8 +50,8 @@ VkLayerDispatchTable *get_dispatch_table(device_table_map &map, void* object);
 
 VkLayerInstanceDispatchTable *get_dispatch_table(instance_table_map &map, void* object);
 
-VkLayerInstanceCreateInfo *get_chain_info(const VkInstanceCreateInfo *pCreateInfo);
-VkLayerDeviceCreateInfo *get_chain_info(const VkDeviceCreateInfo *pCreateInfo);
+VkLayerInstanceCreateInfo *get_chain_info(const VkInstanceCreateInfo *pCreateInfo, VkLayerFunction func);
+VkLayerDeviceCreateInfo *get_chain_info(const VkDeviceCreateInfo *pCreateInfo, VkLayerFunction func);
 
 void destroy_device_dispatch_table(dispatch_key key);
 void destroy_instance_dispatch_table(dispatch_key key);
index 9a3aa3f..82aaafa 100644 (file)
@@ -1140,21 +1140,19 @@ static void loader_destroy_logical_device(const struct loader_instance *inst,
 
 static struct loader_device *loader_add_logical_device(
                                         const struct loader_instance *inst,
-                                        const VkDevice dev,
                                         struct loader_device **device_list)
 {
     struct loader_device *new_dev;
 
     new_dev = loader_heap_alloc(inst, sizeof(struct loader_device), VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
     if (!new_dev) {
-        loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to alloc struct laoder-device");
+        loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to alloc struct loader-device");
         return NULL;
     }
 
     memset(new_dev, 0, sizeof(struct loader_device));
 
     new_dev->next = *device_list;
-    new_dev->device = dev;
     *device_list = new_dev;
     return new_dev;
 }
@@ -2295,6 +2293,13 @@ void loader_layer_scan(
 
 static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_gpa_instance_internal(VkInstance inst, const char * pName)
 {
+    if (!strcmp(pName, "vkGetInstanceProcAddr"))
+        return (void *) loader_gpa_instance_internal;
+    if (!strcmp(pName, "vkCreateInstance"))
+        return (void *) loader_CreateInstance;
+    if (!strcmp(pName, "vkCreateDevice"))
+        return (void *) loader_create_device_terminator;
+
     // inst is not wrapped
     if (inst == VK_NULL_HANDLE) {
         return NULL;
@@ -2302,9 +2307,6 @@ static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_gpa_instance_internal(VkI
     VkLayerInstanceDispatchTable* disp_table = * (VkLayerInstanceDispatchTable **) inst;
     void *addr;
 
-    if (!strcmp(pName, "vkGetInstanceProcAddr"))
-        return (void *) loader_gpa_instance_internal;
-
     if (disp_table == NULL)
         return NULL;
 
@@ -2785,19 +2787,17 @@ VkResult loader_enable_instance_layers(
     }
 
     /* Add any implicit layers first */
-    loader_add_layer_implicit(
-                                inst,
-                                VK_LAYER_TYPE_INSTANCE_IMPLICIT,
-                                &inst->activated_layer_list,
-                                instance_layers);
+    loader_add_layer_implicit(inst,
+                              VK_LAYER_TYPE_INSTANCE_IMPLICIT,
+                              &inst->activated_layer_list,
+                              instance_layers);
 
     /* Add any layers specified via environment variable next */
-    loader_add_layer_env(
-                            inst,
-                            VK_LAYER_TYPE_INSTANCE_EXPLICIT,
-                            "VK_INSTANCE_LAYERS",
-                            &inst->activated_layer_list,
-                            instance_layers);
+    loader_add_layer_env(inst,
+                         VK_LAYER_TYPE_INSTANCE_EXPLICIT,
+                         "VK_INSTANCE_LAYERS",
+                         &inst->activated_layer_list,
+                         instance_layers);
 
     /* Add layers specified by the application */
     err = loader_add_layer_names_to_list(
@@ -2810,87 +2810,116 @@ VkResult loader_enable_instance_layers(
     return err;
 }
 
-uint32_t loader_activate_instance_layers(struct loader_instance *inst)
-{
-    uint32_t layer_idx;
-    VkBaseLayerObject *wrappedInstance;
+/*
+ * Given the list of layers to activate in the loader_instance
+ * structure. This function will add a VkLayerInstanceCreateInfo
+ * structure to the VkInstanceCreateInfo.pNext pointer.
+ * Each activated layer will have it's own VkLayerInstanceLink
+ * structure that tells the layer what Get*ProcAddr to call to
+ * get function pointers to the next layer down.
+ * Once the chain info has been created this function will
+ * execute the CreateInstance call chain. Each layer will
+ * then have an opportunity in it's CreateInstance function
+ * to setup it's dispatch table when the lower layer returns
+ * successfully.
+ * Each layer can wrap or not-wrap the returned VkInstance object
+ * as it sees fit.
+ * The instance chain is terminated by a loader function
+ * that will call CreateInstance on all available ICD's and
+ * cache those VkInstance objects for future use.
+ */
+VkResult loader_create_instance_chain(const VkInstanceCreateInfo *pCreateInfo,
+                                      const VkAllocationCallbacks* pAllocator,
+                                      struct loader_instance *inst)
+{
+    uint32_t activated_layers = 0;
+    VkLayerInstanceCreateInfo chain_info;
+    VkLayerInstanceLink *layer_instance_link_info = NULL;
+    VkInstanceCreateInfo loader_create_info;
+    VkResult res;
 
-    if (inst == NULL) {
-        return 0;
-    }
+    PFN_vkGetInstanceProcAddr nextGIPA = loader_gpa_instance_internal;
+    PFN_vkGetInstanceProcAddr fpGIPA = loader_gpa_instance_internal;
 
-    // NOTE inst is unwrapped at this point in time
-    void* baseObj = (void*) inst;
-    void* nextObj = (void*) inst;
-    VkBaseLayerObject *nextInstObj;
-    PFN_vkGetInstanceProcAddr nextGPA = loader_gpa_instance_internal;
+    memcpy(&loader_create_info, pCreateInfo, sizeof(VkInstanceCreateInfo));
 
-    if (!inst->activated_layer_list.count) {
-        loader_init_instance_core_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj, (VkInstance) baseObj);
-        return 0;
-    }
+    if (inst->activated_layer_list.count > 0) {
 
-    wrappedInstance = loader_stack_alloc(sizeof(VkBaseLayerObject)
-                                   * inst->activated_layer_list.count);
-    if (!wrappedInstance) {
-        loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to alloc Instance objects for layer");
-        return 0;
-    }
+        chain_info.u.pLayerInfo = NULL;
+        chain_info.pNext = pCreateInfo->pNext;
+        chain_info.sType = VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO;
+        chain_info.function = VK_LAYER_LINK_INFO;
+        loader_create_info.pNext = &chain_info;
 
-    /* Create instance chain of enabled layers */
-    layer_idx = inst->activated_layer_list.count - 1;
-    for (int32_t i = inst->activated_layer_list.count - 1; i >= 0; i--) {
-        struct loader_layer_properties *layer_prop = &inst->activated_layer_list.list[i];
-        loader_platform_dl_handle lib_handle;
-
-         /*
-         * Note: An extension's Get*ProcAddr should not return a function pointer for
-         * any extension entry points until the extension has been enabled.
-         * To do this requires a different behavior from Get*ProcAddr functions implemented
-         * in layers.
-         * The very first call to a layer will be it's Get*ProcAddr function requesting
-         * the layer's vkGet*ProcAddr. The layer should initialize its internal dispatch table
-         * with the wrapped object given (either Instance or Device) and return the layer's
-         * Get*ProcAddr function. The layer should also use this opportunity to record the
-         * baseObject so that it can find the correct local dispatch table on future calls.
-         * Subsequent calls to Get*ProcAddr, CreateInstance, CreateDevice
-         * will not use a wrapped object and must look up their local dispatch table from
-         * the given baseObject.
-         */
-        nextInstObj = (wrappedInstance + layer_idx);
-        nextInstObj->pGPA = (PFN_vkGPA) nextGPA;
-        nextInstObj->baseObject = baseObj;
-        nextInstObj->nextObject = nextObj;
-        nextObj = (void*) nextInstObj;
-
-        lib_handle = loader_add_layer_lib(inst, "instance", layer_prop);
-        if (!lib_handle)
-            continue;   // TODO what should we do in this case
-        if ((nextGPA = layer_prop->functions.get_instance_proc_addr) == NULL) {
-            if (layer_prop->functions.str_gipa == NULL || strlen(layer_prop->functions.str_gipa) == 0) {
-                nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetInstanceProcAddr");
-                layer_prop->functions.get_instance_proc_addr = nextGPA;
-            } else
-                nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gipa);
-            if (!nextGPA) {
-                loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to find vkGetInstanceProcAddr in layer %s", layer_prop->lib_name);
-
-                /* TODO: Should we return nextObj, nextGPA to previous? or decrement layer_list count*/
-                continue;
+        layer_instance_link_info = loader_stack_alloc(sizeof(VkLayerInstanceLink)
+                                       * inst->activated_layer_list.count);
+        if (!layer_instance_link_info) {
+            loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to alloc Instance objects for layer");
+            return VK_ERROR_OUT_OF_HOST_MEMORY;
+        }
+
+        /* Create instance chain of enabled layers */
+        for (int32_t i = inst->activated_layer_list.count - 1; i >= 0; i--) {
+            struct loader_layer_properties *layer_prop = &inst->activated_layer_list.list[i];
+            loader_platform_dl_handle lib_handle;
+
+            lib_handle = loader_add_layer_lib(inst, "instance", layer_prop);
+            if (!lib_handle)
+                continue;   // TODO what should we do in this case
+            if ((fpGIPA = layer_prop->functions.get_instance_proc_addr) == NULL) {
+                if (layer_prop->functions.str_gipa == NULL || strlen(layer_prop->functions.str_gipa) == 0) {
+                    fpGIPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetInstanceProcAddr");
+                    layer_prop->functions.get_instance_proc_addr = fpGIPA;
+                } else
+                    fpGIPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gipa);
+                if (!fpGIPA) {
+                    loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to find vkGetInstanceProcAddr in layer %s", layer_prop->lib_name);
+
+                    /* TODO: Should we return nextObj, nextGPA to previous? or decrement layer_list count*/
+                    continue;
+                }
             }
+
+            layer_instance_link_info[activated_layers].pNext = chain_info.u.pLayerInfo;
+            layer_instance_link_info[activated_layers].pfnNextGetInstanceProcAddr = nextGIPA;
+            chain_info.u.pLayerInfo = &layer_instance_link_info[activated_layers];
+            nextGIPA = fpGIPA;
+
+           loader_log(inst, VK_DEBUG_REPORT_INFO_BIT_EXT, 0,
+                      "Insert instance layer %s (%s)",
+                      layer_prop->info.layerName,
+                      layer_prop->lib_name);
+
+            activated_layers++;
         }
+    }
+
+    PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance) nextGIPA(VK_NULL_HANDLE, "vkCreateInstance");
+    if (fpCreateInstance) {
+        VkLayerInstanceCreateInfo instance_create_info;
+
+        instance_create_info.sType = VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO;
+        instance_create_info.function = VK_LAYER_INSTANCE_INFO;
+
+        instance_create_info.u.instanceInfo.instance_info = inst;
+        instance_create_info.u.instanceInfo.pfnNextGetInstanceProcAddr= nextGIPA;
 
-        loader_log(inst, VK_DEBUG_REPORT_INFO_BIT_EXT, 0,
-                   "Insert instance layer %s (%s)",
-                   layer_prop->info.layerName,
-                   layer_prop->lib_name);
+        instance_create_info.pNext = loader_create_info.pNext;
+        loader_create_info.pNext = &instance_create_info;
 
-        layer_idx--;
+        res = fpCreateInstance(&loader_create_info, pAllocator, &inst->instance);
+    } else {
+        // Couldn't find CreateInstance function!
+        res = VK_ERROR_INITIALIZATION_FAILED;
     }
 
-    loader_init_instance_core_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj, (VkInstance) baseObj);
+    if (res != VK_SUCCESS) {
+        // TODO: Need to clean up here
+    } else {
+        loader_init_instance_core_dispatch_table(inst->disp, nextGIPA, inst->instance);
+    }
 
-    return inst->activated_layer_list.count;
+    return res;
 }
 
 void loader_activate_instance_layer_extensions(struct loader_instance *inst, VkInstance created_inst)
@@ -2948,100 +2977,164 @@ static VkResult loader_enable_device_layers(
     return err;
 }
 
-/*
- * This function terminates the device chain for CreateDevice.
- * CreateDevice is a special case and so the loader call's
- * the ICD's CreateDevice before creating the chain. Since
- * we can't call CreateDevice twice we must terminate the
- * device chain with something else.
- */
-static VKAPI_ATTR VkResult VKAPI_CALL scratch_vkCreateDevice(
-    VkPhysicalDevice          physicalDevice,
-    const VkDeviceCreateInfo *pCreateInfo,
-    const VkAllocationCallbacks*   pAllocator,
-    VkDevice                 *pDevice)
+VkResult loader_create_device_terminator(
+        VkPhysicalDevice                            physicalDevice,
+        const VkDeviceCreateInfo*                   pCreateInfo,
+        const VkAllocationCallbacks*                pAllocator,
+        VkDevice*                                   pDevice)
 {
-    return VK_SUCCESS;
+    struct loader_physical_device *phys_dev;
+    phys_dev = loader_get_physical_device(physicalDevice);
+
+    VkLayerDeviceCreateInfo *chain_info = (VkLayerDeviceCreateInfo *) pCreateInfo->pNext;
+    while (chain_info && !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO
+           && chain_info->function == VK_LAYER_DEVICE_INFO)) {
+        chain_info = (VkLayerDeviceCreateInfo *) chain_info->pNext;
+    }
+    assert(chain_info != NULL);
+
+    struct loader_device *dev = (struct loader_device *) chain_info->u.deviceInfo.device_info;
+    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.deviceInfo.pfnNextGetInstanceProcAddr;
+    PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice) fpGetInstanceProcAddr(phys_dev->this_icd->instance, "vkCreateDevice");
+    if (fpCreateDevice == NULL) {
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
+    VkDeviceCreateInfo localCreateInfo;
+    memcpy(&localCreateInfo, pCreateInfo, sizeof(localCreateInfo));
+    localCreateInfo.pNext = NULL;
+    // ICDs do not support layers
+    localCreateInfo.enabledLayerCount = 0;
+    localCreateInfo.ppEnabledLayerNames = NULL;
+
+    VkDevice localDevice;
+    VkResult res = fpCreateDevice(phys_dev->phys_dev, &localCreateInfo, pAllocator, &localDevice);
+
+    if (res != VK_SUCCESS) {
+        return res;
+    }
+
+    *pDevice = localDevice;
+
+    /* Init dispatch pointer in new device object */
+    loader_init_dispatch(*pDevice, &dev->loader_dispatch);
+
+    return res;
 }
 
-static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_GetDeviceChainProcAddr(VkDevice device, const char * name)
+VkResult loader_create_device_chain(
+        VkPhysicalDevice physicalDevice,
+        const VkDeviceCreateInfo *pCreateInfo,
+        const VkAllocationCallbacks* pAllocator,
+        struct loader_instance *inst,
+        struct loader_icd *icd,
+        struct loader_device *dev)
 {
-    if (!strcmp(name, "vkGetDeviceProcAddr"))
-        return (PFN_vkVoidFunction) loader_GetDeviceChainProcAddr;
-    if (!strcmp(name, "vkCreateDevice"))
-        return (PFN_vkVoidFunction) scratch_vkCreateDevice;
+    uint32_t activated_layers = 0;
+    VkLayerDeviceLink *layer_device_link_info;
+    VkLayerDeviceCreateInfo chain_info;
+    VkLayerDeviceCreateInfo device_info;
+    VkDeviceCreateInfo loader_create_info;
+    VkResult res;
 
-    struct loader_device *found_dev;
-    struct loader_icd *icd = loader_get_icd_and_device(device, &found_dev);
-    return icd->GetDeviceProcAddr(device, name);
-}
+    PFN_vkGetDeviceProcAddr fpGDPA, nextGDPA = icd->GetDeviceProcAddr;
+    PFN_vkGetInstanceProcAddr fpGIPA, nextGIPA = loader_gpa_instance_internal;
 
-static uint32_t loader_activate_device_layers(
-        const struct loader_instance *inst,
-        struct loader_device *dev,
-        VkDevice device)
-{
-    if (!dev) {
-        return 0;
-    }
-
-    /* activate any layer libraries */
-    void* nextObj = (void*) device;
-    void* baseObj = nextObj;
-    VkBaseLayerObject *nextGpuObj;
-    PFN_vkGetDeviceProcAddr nextGPA = loader_GetDeviceChainProcAddr;
-    VkBaseLayerObject *wrappedGpus;
-
-    if (!dev->activated_layer_list.count) {
-        loader_init_device_dispatch_table(&dev->loader_dispatch, nextGPA,
-            (VkDevice) nextObj, (VkDevice) baseObj);
-        return 0;
-    }
-
-    wrappedGpus = loader_heap_alloc(inst,
-                    sizeof (VkBaseLayerObject) * dev->activated_layer_list.count,
-                    VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
-    if (!wrappedGpus) {
-        loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to alloc Gpu objects for layer");
-        return 0;
-    }
-
-    for (int32_t i = dev->activated_layer_list.count - 1; i >= 0; i--) {
-
-        struct loader_layer_properties *layer_prop = &dev->activated_layer_list.list[i];
-        loader_platform_dl_handle lib_handle;
-
-        nextGpuObj = (wrappedGpus + i);
-        nextGpuObj->pGPA = (PFN_vkGPA)nextGPA;
-        nextGpuObj->baseObject = baseObj;
-        nextGpuObj->nextObject = nextObj;
-        nextObj = (void*) nextGpuObj;
-
-        lib_handle = loader_add_layer_lib(inst, "device", layer_prop);
-        if ((nextGPA = layer_prop->functions.get_device_proc_addr) == NULL) {
-            if (layer_prop->functions.str_gdpa == NULL || strlen(layer_prop->functions.str_gdpa) == 0) {
-                nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetDeviceProcAddr");
-                layer_prop->functions.get_device_proc_addr = nextGPA;
-            } else
-                nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gdpa);
-            if (!nextGPA) {
-                loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to find vkGetDeviceProcAddr in layer %s", layer_prop->lib_name);
-                continue;
+    memcpy(&loader_create_info, pCreateInfo, sizeof(VkDeviceCreateInfo));
+
+    chain_info.sType = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO;
+    chain_info.function = VK_LAYER_LINK_INFO;
+    chain_info.u.pLayerInfo = NULL;
+    chain_info.pNext = pCreateInfo->pNext;
+
+    layer_device_link_info = loader_stack_alloc(sizeof(VkLayerDeviceLink)
+                                   * dev->activated_layer_list.count);
+    if (!layer_device_link_info) {
+        loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to alloc Device objects for layer");
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+    }
+
+    /*
+     * This structure is used by loader_create_device_terminator
+     * so that it can intialize the device dispatch table pointer
+     * in the device object returned by the ICD. Without this
+     * structure the code wouldn't know where the loader's device_info
+     * structure is located.
+     */
+    device_info.sType = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO;
+    device_info.function = VK_LAYER_DEVICE_INFO;
+    device_info.pNext = &chain_info;
+    device_info.u.deviceInfo.device_info = dev;
+    device_info.u.deviceInfo.pfnNextGetInstanceProcAddr = icd->this_icd_lib->GetInstanceProcAddr;
+
+    loader_create_info.pNext = &device_info;
+
+    if (dev->activated_layer_list.count > 0) {
+        /* Create instance chain of enabled layers */
+        for (int32_t i = dev->activated_layer_list.count - 1; i >= 0; i--) {
+            struct loader_layer_properties *layer_prop = &dev->activated_layer_list.list[i];
+            loader_platform_dl_handle lib_handle;
+
+            lib_handle = loader_add_layer_lib(inst, "device", layer_prop);
+            if (!lib_handle)
+                continue;   // TODO what should we do in this case
+            if ((fpGIPA = layer_prop->functions.get_instance_proc_addr) == NULL) {
+                if (layer_prop->functions.str_gipa == NULL || strlen(layer_prop->functions.str_gipa) == 0) {
+                    fpGIPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetInstanceProcAddr");
+                    layer_prop->functions.get_instance_proc_addr = fpGIPA;
+                } else
+                    fpGIPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gipa);
+                if (!fpGIPA) {
+                    loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to find vkGetInstanceProcAddr in layer %s", layer_prop->lib_name);
+
+                    /* TODO: Should we return nextObj, nextGPA to previous? or decrement layer_list count*/
+                    continue;
+                }
             }
-        }
+            if ((fpGDPA = layer_prop->functions.get_device_proc_addr) == NULL) {
+                if (layer_prop->functions.str_gdpa == NULL || strlen(layer_prop->functions.str_gdpa) == 0) {
+                    fpGDPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetDeviceProcAddr");
+                    layer_prop->functions.get_device_proc_addr = fpGDPA;
+                } else
+                    fpGDPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gdpa);
+                if (!fpGDPA) {
+                    loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to find vkGetDeviceProcAddr in layer %s", layer_prop->lib_name);
+
+                    /* TODO: Should we return nextObj, nextGPA to previous? or decrement layer_list count*/
+                    continue;
+                }
+            }
+
+            layer_device_link_info[activated_layers].pNext = chain_info.u.pLayerInfo;
+            layer_device_link_info[activated_layers].pfnNextGetInstanceProcAddr = nextGIPA;
+            layer_device_link_info[activated_layers].pfnNextGetDeviceProcAddr = nextGDPA;
+            chain_info.u.pLayerInfo = &layer_device_link_info[activated_layers];
+            nextGIPA = fpGIPA;
+            nextGDPA = fpGDPA;
 
-        loader_log(inst, VK_DEBUG_REPORT_INFO_BIT_EXT, 0,
-                   "Insert device layer library %s (%s)",
-                   layer_prop->info.layerName,
-                   layer_prop->lib_name);
+            loader_log(inst, VK_DEBUG_REPORT_INFO_BIT_EXT, 0,
+                       "Insert device layer %s (%s)",
+                       layer_prop->info.layerName,
+                       layer_prop->lib_name);
 
+            activated_layers++;
+        }
     }
 
-    loader_init_device_dispatch_table(&dev->loader_dispatch, nextGPA,
-            (VkDevice) nextObj, (VkDevice) baseObj);
-    loader_heap_free(inst, wrappedGpus);
+    PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice) nextGIPA(VK_NULL_HANDLE, "vkCreateDevice");
+    if (fpCreateDevice) {
+        res = fpCreateDevice(physicalDevice, &loader_create_info, pAllocator, &dev->device);
+    } else {
+        // Couldn't find CreateDevice function!
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
+    /* Initialize device dispatch table */
+    loader_init_device_dispatch_table(&dev->loader_dispatch,
+                                      nextGDPA,
+                                      dev->device);
 
-    return dev->activated_layer_list.count;
+    return res;
 }
 
 VkResult loader_validate_layers(
@@ -3149,7 +3242,6 @@ VKAPI_ATTR VkResult VKAPI_CALL loader_CreateInstance(
         const VkAllocationCallbacks*    pAllocator,
         VkInstance*                     pInstance)
 {
-    struct loader_instance *ptr_instance = *(struct loader_instance **) pInstance;
     struct loader_icd *icd;
     VkExtensionProperties *prop;
     char **filtered_extension_names = NULL;
@@ -3157,11 +3249,22 @@ VKAPI_ATTR VkResult VKAPI_CALL loader_CreateInstance(
     VkResult res = VK_SUCCESS;
     bool success = false;
 
+    VkLayerInstanceCreateInfo *chain_info = (VkLayerInstanceCreateInfo *) pCreateInfo->pNext;
+    while (chain_info && !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO
+           && chain_info->function == VK_LAYER_INSTANCE_INFO)) {
+        chain_info = (VkLayerInstanceCreateInfo *) chain_info->pNext;
+    }
+    assert(chain_info != NULL);
+
+    struct loader_instance *ptr_instance = (struct loader_instance *) chain_info->u.instanceInfo.instance_info;
     memcpy(&icd_create_info, pCreateInfo, sizeof(icd_create_info));
 
     icd_create_info.enabledLayerCount = 0;
     icd_create_info.ppEnabledLayerNames = NULL;
 
+    // TODO: Should really strip off the VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO entries
+    icd_create_info.pNext = NULL;
+
     /*
      * NOTE: Need to filter the extensions to only those
      * supported by the ICD.
@@ -3233,6 +3336,8 @@ VKAPI_ATTR VkResult VKAPI_CALL loader_CreateInstance(
         }
     }
 
+    *pInstance = (VkInstance) ptr_instance;
+
     return VK_SUCCESS;
 }
 
@@ -3362,6 +3467,7 @@ VKAPI_ATTR VkResult VKAPI_CALL loader_EnumeratePhysicalDevices(
         VkPhysicalDevice*                       pPhysicalDevices)
 {
     uint32_t i;
+    uint32_t copy_count = 0;
     struct loader_instance *ptr_instance = (struct loader_instance *) instance;
     VkResult res = VK_SUCCESS;
 
@@ -3374,9 +3480,15 @@ VKAPI_ATTR VkResult VKAPI_CALL loader_EnumeratePhysicalDevices(
         return res;
     }
 
-    for (i = 0; i < ptr_instance->total_gpu_count; i++) {
+    copy_count = (ptr_instance->total_gpu_count < *pPhysicalDeviceCount) ? ptr_instance->total_gpu_count : *pPhysicalDeviceCount;
+    for (i = 0; i < copy_count; i++) {
         pPhysicalDevices[i] = (VkPhysicalDevice) &ptr_instance->phys_devs[i];
     }
+    *pPhysicalDeviceCount = copy_count;
+
+    if (copy_count < ptr_instance->total_gpu_count) {
+        return VK_INCOMPLETE;
+    }
 
     return res;
 }
@@ -3578,21 +3690,12 @@ VKAPI_ATTR VkResult VKAPI_CALL loader_CreateDevice(
         }
     }
 
-    // since physicalDevice object maybe wrapped by a layer need to get unwrapped version
-    // we haven't yet called down the chain for the layer to unwrap the object
-    res = icd->CreateDevice(phys_dev->phys_dev, &device_create_info, pAllocator, pDevice);
-    if (res != VK_SUCCESS) {
-        loader_destroy_generic_list(inst, (struct loader_generic_list *) &activated_layer_list);
-        return res;
-    }
-
-    dev = loader_add_logical_device(inst, *pDevice, &icd->logical_device_list);
+    dev = loader_add_logical_device(inst, &icd->logical_device_list);
     if (dev == NULL) {
         loader_destroy_generic_list(inst, (struct loader_generic_list *) &activated_layer_list);
         return VK_ERROR_OUT_OF_HOST_MEMORY;
     }
 
-    loader_init_dispatch(*pDevice, &dev->loader_dispatch);
 
     /* move the locally filled layer list into the device, and pass ownership of the memory */
     dev->activated_layer_list.capacity = activated_layer_list.capacity;
@@ -3600,11 +3703,20 @@ VKAPI_ATTR VkResult VKAPI_CALL loader_CreateDevice(
     dev->activated_layer_list.list = activated_layer_list.list;
     memset(&activated_layer_list, 0, sizeof(activated_layer_list));
 
-   /* activate any layers on device chain which terminates with device*/
-    loader_activate_device_layers(inst, dev, *pDevice);
+    /* activate any layers on device chain which terminates with device*/
+    res = loader_enable_device_layers(inst, icd, &dev->activated_layer_list, pCreateInfo, &inst->device_layer_list);
+    if (res != VK_SUCCESS) {
+        loader_destroy_logical_device(inst, dev);
+        return res;
+    }
+
+    res = loader_create_device_chain(physicalDevice, pCreateInfo, pAllocator, inst, icd, dev);
+    if (res != VK_SUCCESS) {
+        loader_destroy_logical_device(inst, dev);
+        return res;
+    }
 
-    /* finally can call down the chain */
-    res = dev->loader_dispatch.core_dispatch.CreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
+    *pDevice = dev->device;
 
     /* initialize any device extension dispatch entry's from the instance list*/
     loader_init_dispatch_dev_ext(inst, dev);
@@ -3614,7 +3726,6 @@ VKAPI_ATTR VkResult VKAPI_CALL loader_CreateDevice(
     loader_init_device_extension_dispatch_table(&dev->loader_dispatch,
                                                 dev->loader_dispatch.core_dispatch.GetDeviceProcAddr,
                                                 *pDevice);
-    dev->loader_dispatch.core_dispatch.CreateDevice = icd->CreateDevice;
 
     return res;
 }
index b5b3d2c..55662b7 100644 (file)
@@ -241,6 +241,8 @@ struct loader_instance {
 
     struct loader_layer_list activated_layer_list;
 
+    VkInstance instance;
+
     bool debug_report_enabled;
     VkLayerDbgFunctionNode *DbgFunctionHead;
 
@@ -425,6 +427,12 @@ VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceMemoryProperties (
         VkPhysicalDevice physicalDevice,
         VkPhysicalDeviceMemoryProperties * pProperties);
 
+VkResult loader_create_device_terminator(
+        VkPhysicalDevice                            physicalDevice,
+        const VkDeviceCreateInfo*                   pCreateInfo,
+        const VkAllocationCallbacks*                pAllocator,
+        VkDevice*                                   pDevice);
+
 VKAPI_ATTR VkResult VKAPI_CALL loader_CreateDevice(
         VkPhysicalDevice                        gpu,
         const VkDeviceCreateInfo*               pCreateInfo,
@@ -490,7 +498,11 @@ VkResult loader_enable_instance_layers(
         const VkInstanceCreateInfo *pCreateInfo,
         const struct loader_layer_list *instance_layers);
 void loader_deactivate_instance_layers(struct loader_instance *instance);
-uint32_t loader_activate_instance_layers(struct loader_instance *inst);
+
+VkResult loader_create_instance_chain(const VkInstanceCreateInfo *pCreateInfo,
+                                      const VkAllocationCallbacks* pAllocator,
+                                      struct loader_instance *inst);
+
 void loader_activate_instance_layer_extensions(struct loader_instance *inst, VkInstance created_inst);
 
 void* loader_heap_alloc(
index 1577409..1ddef20 100644 (file)
@@ -38,17 +38,14 @@ static VkResult vkDevExtError(VkDevice dev)
 
 static inline void loader_init_device_dispatch_table(struct loader_dev_dispatch_table *dev_table,
                                                     PFN_vkGetDeviceProcAddr gpa,
-                                                    VkDevice dev_next,
                                                     VkDevice dev)
 {
     VkLayerDispatchTable *table = &dev_table->core_dispatch;
     for (uint32_t i = 0; i < MAX_NUM_DEV_EXTS; i++)
         dev_table->ext_dispatch.DevExt[i] = (PFN_vkDevExt) vkDevExtError;
-    // If layer is next, this will trigger layers to initialize their dispatch tables
-    //then use the gpa in their dispatch for subsequent layers in the chain
-    table->GetDeviceProcAddr = (PFN_vkGetDeviceProcAddr) gpa(dev_next, "vkGetDeviceProcAddr");
 
-    table->CreateDevice = (PFN_vkCreateDevice) gpa(dev, "vkCreateDevice");
+    table->GetDeviceProcAddr = (PFN_vkGetDeviceProcAddr) gpa(dev, "vkGetDeviceProcAddr");
+//    table->CreateDevice = (PFN_vkCreateDevice) gpa(dev, "vkCreateDevice");
     table->DestroyDevice = (PFN_vkDestroyDevice) gpa(dev, "vkDestroyDevice");
     table->GetDeviceQueue = (PFN_vkGetDeviceQueue) gpa(dev, "vkGetDeviceQueue");
     table->QueueSubmit = (PFN_vkQueueSubmit) gpa(dev, "vkQueueSubmit");
@@ -194,8 +191,8 @@ static inline void *loader_lookup_device_dispatch_table(
     name += 2;
     if (!strcmp(name, "GetDeviceProcAddr"))
         return (void *) table->GetDeviceProcAddr;
-    if (!strcmp(name, "CreateDevice"))
-        return (void *) table->CreateDevice;
+//    if (!strcmp(name, "CreateDevice"))
+//        return (void *) table->CreateDevice;
     if (!strcmp(name, "DestroyDevice"))
         return (void *) table->DestroyDevice;
     if (!strcmp(name, "GetDeviceQueue"))
@@ -440,17 +437,15 @@ static inline void *loader_lookup_device_dispatch_table(
     return NULL;
 }
 
-static inline void loader_init_instance_core_dispatch_table(VkLayerInstanceDispatchTable *table,
-                                                PFN_vkGetInstanceProcAddr gpa,
-                                                VkInstance inst_next,
-                                                VkInstance inst)
+static inline void loader_init_instance_core_dispatch_table(
+        VkLayerInstanceDispatchTable *table,
+        PFN_vkGetInstanceProcAddr gpa,
+        VkInstance inst)
 {
-    // If layer is next, this will trigger layers to initialize their dispatch tables
-    //then use the gpa in their dispatch for subsequent layers in the chain
-    table->GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr) gpa(inst_next, "vkGetInstanceProcAddr");
-
+    table->GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr) gpa(inst, "vkGetInstanceProcAddr");
     table->CreateInstance = (PFN_vkCreateInstance) gpa(inst, "vkCreateInstance");
     table->DestroyInstance = (PFN_vkDestroyInstance) gpa(inst, "vkDestroyInstance");
+    table->CreateDevice = (PFN_vkCreateDevice) gpa(inst, "vkCreateDevice");
     table->EnumeratePhysicalDevices = (PFN_vkEnumeratePhysicalDevices) gpa(inst, "vkEnumeratePhysicalDevices");
     table->GetPhysicalDeviceFeatures = (PFN_vkGetPhysicalDeviceFeatures) gpa(inst, "vkGetPhysicalDeviceFeatures");
     table->GetPhysicalDeviceImageFormatProperties = (PFN_vkGetPhysicalDeviceImageFormatProperties) gpa(inst, "vkGetPhysicalDeviceImageFormatProperties");
@@ -510,6 +505,8 @@ static inline void *loader_lookup_instance_dispatch_table(
         return (void *) table->CreateInstance;
     if (!strcmp(name, "DestroyInstance"))
         return (void *) table->DestroyInstance;
+    if (!strcmp(name, "CreateDevice"))
+        return (void *) table->CreateDevice;
     if (!strcmp(name, "EnumeratePhysicalDevices"))
         return (void *) table->EnumeratePhysicalDevices;
     if (!strcmp(name, "GetPhysicalDeviceFeatures"))
index 563fec6..d525158 100644 (file)
@@ -176,24 +176,28 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(
         loader_heap_free(ptr_instance, ptr_instance);
         return res;
     }
-    loader_activate_instance_layers(ptr_instance);
-
-    wsi_create_instance(ptr_instance, pCreateInfo);
-    debug_report_create_instance(ptr_instance, pCreateInfo);
 
     created_instance = (VkInstance) ptr_instance;
-    res = ptr_instance->disp->CreateInstance(pCreateInfo, pAllocator, &created_instance);
+    res = loader_create_instance_chain(pCreateInfo, pAllocator, ptr_instance);
 
     if (res == VK_SUCCESS) {
+        wsi_create_instance(ptr_instance, pCreateInfo);
+        debug_report_create_instance(ptr_instance, pCreateInfo);
+
         *pInstance = created_instance;
+
         /*
+         * TODO: This can go away now?
          * Finally have the layers in place and everyone has seen
          * the CreateInstance command go by. This allows the layer's
          * GetInstanceProcAddr functions to return valid extension functions
          * if enabled.
          */
         loader_activate_instance_layer_extensions(ptr_instance, *pInstance);
+    } else {
+        // TODO: cleanup here.
     }
+
     /* Remove temporary debug_report callback */
     util_DestroyDebugReportCallback(ptr_instance, instance_callback, pAllocator);
 
index bed5664..7b1b0f7 100755 (executable)
@@ -116,41 +116,34 @@ class DispatchTableOpsSubcommand(Subcommand):
         func = []
         if type == "device":
             # GPA has to be first one and uses wrapped object
-            stmts.append("VkDevice device = (VkDevice) devw->nextObject;")
-            stmts.append("PFN_vkGetDeviceProcAddr gpa = (PFN_vkGetDeviceProcAddr) devw->pGPA;")
-            stmts.append("VkDevice baseDevice = (VkDevice) devw->baseObject;")
-            stmts.append("// GPA has to be first entry inited and uses wrapped object since it triggers init")
             stmts.append("memset(table, 0, sizeof(*table));")
             stmts.append("table->GetDeviceProcAddr =(PFN_vkGetDeviceProcAddr)  gpa(device,\"vkGetDeviceProcAddr\");")
             for proto in self.protos:
-                if proto.name == "CreateInstance" or proto.name == "EnumerateInstanceExtensionProperties" or proto.name == "EnumerateInstanceLayerProperties" or proto.params[0].ty == "VkInstance" or (proto.params[0].ty == "VkPhysicalDevice" and proto.name != "CreateDevice"):
+                if proto.name == "CreateInstance" or proto.name == "EnumerateInstanceExtensionProperties" or proto.name == "EnumerateInstanceLayerProperties" or proto.params[0].ty == "VkInstance" or proto.params[0].ty == "VkPhysicalDevice":
                     continue
                 if proto.name != "GetDeviceProcAddr" and 'KHR' not in proto.name:
-                    stmts.append("table->%s = (PFN_vk%s) gpa(baseDevice, \"vk%s\");" %
+                    stmts.append("table->%s = (PFN_vk%s) gpa(device, \"vk%s\");" %
                         (proto.name, proto.name, proto.name))
-            func.append("static inline void %s_initialize_dispatch_table(VkLayerDispatchTable *table,"
+            func.append("static inline void %s_init_device_dispatch_table(VkDevice device,"
                 % self.prefix)
-            func.append("%s                                              const VkBaseLayerObject *devw)"
+            func.append("%s                                               VkLayerDispatchTable *table,"
+                % (" " * len(self.prefix)))
+            func.append("%s                                               PFN_vkGetDeviceProcAddr gpa)"
                 % (" " * len(self.prefix)))
         else:
-            # GPA has to be first one and uses wrapped object
-            stmts.append("VkInstance instance = (VkInstance) instw->nextObject;")
-            stmts.append("PFN_vkGetInstanceProcAddr gpa = (PFN_vkGetInstanceProcAddr) instw->pGPA;")
-            stmts.append("VkInstance baseInstance = (VkInstance) instw->baseObject;")
-            stmts.append("// GPA has to be first entry inited and uses wrapped object since it triggers init")
             stmts.append("table->GetInstanceProcAddr =(PFN_vkGetInstanceProcAddr)  gpa(instance,\"vkGetInstanceProcAddr\");")
             for proto in self.protos:
-                if proto.name != "CreateInstance"  and proto.params[0].ty != "VkInstance" and proto.params[0].ty != "VkPhysicalDevice":
+                if proto.params[0].ty != "VkInstance" and proto.params[0].ty != "VkPhysicalDevice":
                     continue
                 if proto.name == "CreateDevice":
                     continue
                 if proto.name != "GetInstanceProcAddr" and 'KHR' not in proto.name:
-                    stmts.append("table->%s = (PFN_vk%s) gpa(baseInstance, \"vk%s\");" %
+                    stmts.append("table->%s = (PFN_vk%s) gpa(instance, \"vk%s\");" %
                           (proto.name, proto.name, proto.name))
-            func.append("static inline void %s_init_instance_dispatch_table(VkLayerInstanceDispatchTable *table,"
-                % self.prefix)
-            func.append("%s                                              const VkBaseLayerObject *instw)"
-                % (" " * len(self.prefix)))
+            func.append("static inline void %s_init_instance_dispatch_table(" % self.prefix)
+            func.append("%s        VkInstance instance," % (" " * len(self.prefix)))
+            func.append("%s        VkLayerInstanceDispatchTable *table," % (" " * len(self.prefix)))
+            func.append("%s        PFN_vkGetInstanceProcAddr gpa)" % (" " * len(self.prefix)))
         func.append("{")
         func.append("    %s" % "\n    ".join(stmts))
         func.append("}")
index f8518ee..d243596 100755 (executable)
@@ -473,6 +473,8 @@ class Subcommand(object):
 
             if not proto in intercepted:
                 continue
+            if proto.name == "CreateInstance":
+                continue
             if proto.name == "CreateDevice":
                 continue
             lookups.append("if (!strcmp(name, \"%s\"))" % proto.name)
@@ -508,17 +510,15 @@ class Subcommand(object):
             func_body.append("VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char* funcName)\n"
                              "{\n"
                              "    PFN_vkVoidFunction addr;\n"
-                             "    if (device == VK_NULL_HANDLE) {\n"
-                             "        return NULL;\n"
-                             "    }\n"
-                             "    /* loader uses this to force layer initialization; device object is wrapped */\n"
                              "    if (!strcmp(\"vkGetDeviceProcAddr\", funcName)) {\n"
-                             "        initDeviceTable(%s_device_table_map, (const VkBaseLayerObject *) device);\n"
                              "        return (PFN_vkVoidFunction) vkGetDeviceProcAddr;\n"
                              "    }\n\n"
                              "    addr = layer_intercept_proc(funcName);\n"
                              "    if (addr)\n"
-                             "        return addr;" % self.layer_name)
+                             "        return addr;\n"
+                             "    if (device == VK_NULL_HANDLE) {\n"
+                             "        return NULL;\n"
+                             "    }\n")
             if 0 != len(extensions):
                 func_body.append('%s' % self.lineinfo.get())
                 func_body.append('    layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);')
@@ -539,18 +539,20 @@ class Subcommand(object):
             func_body.append("VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char* funcName)\n"
                              "{\n"
                              "    PFN_vkVoidFunction addr;\n"
-                             "    if (instance == VK_NULL_HANDLE) {\n"
-                             "        return NULL;\n"
-                             "    }\n"
-                             "    /* loader uses this to force layer initialization; instance object is wrapped */\n"
-                             "    if (!strcmp(\"vkGetInstanceProcAddr\", funcName)) {\n"
-                             "        initInstanceTable(%s_instance_table_map, (const VkBaseLayerObject *) instance);\n"
+                             "    if (!strcmp(funcName, \"vkGetInstanceProcAddr\"))\n"
                              "        return (PFN_vkVoidFunction) vkGetInstanceProcAddr;\n"
-                             "    }\n\n"
+                             "    if (!strcmp(funcName, \"vkCreateInstance\"))\n"
+                             "        return (PFN_vkVoidFunction) vkCreateInstance;\n"
+                             "    if (!strcmp(funcName, \"vkCreateDevice\"))\n"
+                             "        return (PFN_vkVoidFunction) vkCreateDevice;\n"
                              "    addr = layer_intercept_instance_proc(funcName);\n"
                              "    if (addr) {\n"
                              "        return addr;"
-                             "    }\n" % self.layer_name)
+                             "    }\n"
+                             "    if (instance == VK_NULL_HANDLE) {\n"
+                             "        return NULL;\n"
+                             "    }\n"
+                             )
 
             table_declared = False
             if 0 != len(instance_extensions):
@@ -590,15 +592,10 @@ class Subcommand(object):
             func_body.append('%s' % self.lineinfo.get())
             func_body.append("VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char* funcName)\n"
                              "{\n"
-                             "    PFN_vkVoidFunction addr;\n"
-                             "    if (device == VK_NULL_HANDLE) {\n"
-                             "        return NULL;\n"
-                             "    }\n")
+                             "    PFN_vkVoidFunction addr;\n")
             if self.layer_name == 'generic':
                 func_body.append("\n"
-                             "    /* loader uses this to force layer initialization; device object is wrapped */\n"
                              "    if (!strcmp(\"vkGetDeviceProcAddr\", funcName)) {\n"
-                             "        initDeviceTable((const VkBaseLayerObject *) device);\n"
                              "        return (PFN_vkVoidFunction) vkGetDeviceProcAddr;\n"
                              "    }\n\n"
                              "    addr = layer_intercept_proc(funcName);\n"
@@ -607,14 +604,15 @@ class Subcommand(object):
             else:
                 func_body.append("\n"
                              "    loader_platform_thread_once(&initOnce, init%s);\n\n"
-                             "    /* loader uses this to force layer initialization; device object is wrapped */\n"
                              "    if (!strcmp(\"vkGetDeviceProcAddr\", funcName)) {\n"
-                             "        initDeviceTable((const VkBaseLayerObject *) device);\n"
                              "        return (PFN_vkVoidFunction) vkGetDeviceProcAddr;\n"
                              "    }\n\n"
                              "    addr = layer_intercept_proc(funcName);\n"
                              "    if (addr)\n"
                              "        return addr;" % self.layer_name)
+            func_body.append("    if (device == VK_NULL_HANDLE) {\n"
+                             "        return NULL;\n"
+                             "    }\n")
             func_body.append('')
             func_body.append('    VkLayerDispatchTable *pDisp =  device_dispatch_table(device);')
             if 0 != len(extensions):
@@ -640,32 +638,29 @@ class Subcommand(object):
             func_body.append("VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char* funcName)\n"
                              "{\n"
                              "    PFN_vkVoidFunction addr;\n"
-                             "    if (instance == VK_NULL_HANDLE) {\n"
-                             "        return NULL;\n"
-                             "    }\n")
+                             "    if (!strcmp(funcName, \"vkGetInstanceProcAddr\"))\n"
+                             "        return (PFN_vkVoidFunction) vkGetInstanceProcAddr;\n"
+                             "    if (!strcmp(funcName, \"vkCreateInstance\"))\n"
+                             "        return (PFN_vkVoidFunction) vkCreateInstance;\n"
+                             "    if (!strcmp(funcName, \"vkCreateDevice\"))\n"
+                             "        return (PFN_vkVoidFunction) vkCreateDevice;\n"
+                             )
             if self.layer_name == 'generic':
                 func_body.append("\n"
-                             "    /* loader uses this to force layer initialization; instance object is wrapped */\n"
-                             "    if (!strcmp(\"vkGetInstanceProcAddr\", funcName)) {\n"
-                             "        initInstanceTable((const VkBaseLayerObject *) instance);\n"
-                             "        return (PFN_vkVoidFunction) vkGetInstanceProcAddr;\n"
-                             "    }\n\n"
                              "    addr = layer_intercept_instance_proc(funcName);\n"
                              "    if (addr)\n"
                              "        return addr;")
             else:
                 func_body.append(
                              "    loader_platform_thread_once(&initOnce, init%s);\n\n"
-                             "    /* loader uses this to force layer initialization; instance object is wrapped */\n"
-                             "    if (!strcmp(\"vkGetInstanceProcAddr\", funcName)) {\n"
-                             "        initInstanceTable((const VkBaseLayerObject *) instance);\n"
-                             "        return (PFN_vkVoidFunction) vkGetInstanceProcAddr;\n"
-                             "    }\n\n"
                              "    addr = layer_intercept_instance_proc(funcName);\n"
                              "    if (addr)\n"
                              "        return addr;" % self.layer_name)
+            func_body.append("    if (instance == VK_NULL_HANDLE) {\n"
+                             "        return NULL;\n"
+                             "    }\n")
             func_body.append("")
-            func_body.append("    VkLayerInstanceDispatchTable* pTable = instance_dispatch_table(instance);")
+            func_body.append("    VkLayerInstanceDispatchTable* pTable = instance_dispatch_table(instance);\n")
             if 0 != len(instance_extensions):
                 extra_space = ""
                 for (ext_enable, ext_list) in instance_extensions:
@@ -837,20 +832,32 @@ class GenericLayerSubcommand(Subcommand):
             funcs.append('%s' % self.lineinfo.get())
             funcs.append('%s%s\n'
                      '{\n'
+                     '    layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);\n'
                      '    char str[1024];\n'
-                     '    layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);\n'
                      '    sprintf(str, "At start of Generic layered %s\\n");\n'
-                     '    log_msg(my_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,'
+                     '    log_msg(my_instance_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,'
                      '            (uint64_t)physicalDevice, __LINE__, 0, (char *) "generic", "%%s", (char *) str);\n'
-                     '    %sdevice_dispatch_table(*pDevice)->%s;\n'
-                     '    if (result == VK_SUCCESS) {\n'
-                     '        my_data->report_data = layer_debug_report_create_device(my_data->report_data, *pDevice);\n'
-                     '        createDeviceRegisterExtensions(pCreateInfo, *pDevice);\n'
+                     '    VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);\n'
+                     '    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;\n'
+                     '    PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;\n'
+                     '    PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice) fpGetInstanceProcAddr(NULL, "vkCreateDevice");\n'
+                     '    if (fpCreateDevice == NULL) {\n'
+                     '        return VK_ERROR_INITIALIZATION_FAILED;\n'
                      '    }\n'
+                     '    // Advance the link info for the next element on the chain\n'
+                     '    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;\n'
+                     '    VkResult result = fpCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);\n'
+                     '    if (result != VK_SUCCESS) {\n'
+                     '        return result;\n'
+                     '    }\n'
+                     '    layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);\n'
+                     '    initDeviceTable(*pDevice, fpGetDeviceProcAddr);\n'
+                     '    my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);\n'
+                     '    createDeviceRegisterExtensions(pCreateInfo, *pDevice);\n'
                      '    sprintf(str, "Completed generic layered %s\\n");\n'
-                     '    log_msg(my_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, (uint64_t)physicalDevice, __LINE__, 0, (char *) "generic", "%%s", (char *) str);\n'
+                     '    log_msg(my_device_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, (uint64_t)physicalDevice, __LINE__, 0, (char *) "generic", "%%s", (char *) str);\n'
                      '    %s'
-                     '}' % (qual, decl, proto.name, ret_val, proto.c_call(), proto.name, stmt))
+                     '}' % (qual, decl, proto.name, proto.name, stmt))
         elif proto.name == "DestroyDevice":
             funcs.append('%s' % self.lineinfo.get())
             funcs.append('%s%s\n'
@@ -884,21 +891,31 @@ class GenericLayerSubcommand(Subcommand):
             funcs.append('%s%s\n'
                          '{\n'
                          '    char str[1024];\n'
-                         '    %sinstance_dispatch_table(*pInstance)->%s;\n'
-                         '    if (result == VK_SUCCESS) {\n'
-                         '        createInstanceRegisterExtensions(pCreateInfo, *pInstance);\n'
-                         '        layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);\n'
-                         '        my_data->report_data = debug_report_create_instance(\n'
-                         '                                   instance_dispatch_table(*pInstance),\n'
-                         '                                   *pInstance,\n'
-                         '                                   pCreateInfo->enabledExtensionCount,\n'
-                         '                                   pCreateInfo->ppEnabledExtensionNames);\n'
-                         '        init_generic(my_data, pAllocator);\n'
-                         '        sprintf(str, "Completed generic layered %s\\n");\n'
-                         '        log_msg(my_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, (uint64_t)*pInstance, __LINE__, 0, (char *) "generic", "%%s", (char *) str);\n'
+                         '    VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);\n'
+                         '    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;\n'
+                         '    PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance) fpGetInstanceProcAddr(NULL, "vkCreateInstance");\n'
+                         '    if (fpCreateInstance == NULL) {\n'
+                         '        return VK_ERROR_INITIALIZATION_FAILED;\n'
+                         '    }\n'
+                         '    // Advance the link info for the next element on the chain\n'
+                         '    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;\n'
+                         '    VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);\n'
+                         '    if (result != VK_SUCCESS) {\n'
+                         '        return result;\n'
                          '    }\n'
+                         '    VkLayerInstanceDispatchTable *pTable = initInstanceTable(*pInstance, fpGetInstanceProcAddr);\n'
+                         '    createInstanceRegisterExtensions(pCreateInfo, *pInstance);\n'
+                         '    layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);\n'
+                         '    my_data->report_data = debug_report_create_instance(\n'
+                         '            pTable,\n'
+                         '            *pInstance,\n'
+                         '            pCreateInfo->enabledExtensionCount,\n'
+                         '            pCreateInfo->ppEnabledExtensionNames);\n'
+                         '    init_generic(my_data, pAllocator);\n'
+                         '    sprintf(str, "Completed generic layered %s\\n");\n'
+                         '    log_msg(my_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, (uint64_t)*pInstance, __LINE__, 0, (char *) "generic", "%%s", (char *) str);\n'
                          '    return result;\n'
-                         '}\n' % (qual, decl, ret_val, proto.c_call(), proto.name))
+                         '}\n' % (qual, decl, proto.name))
         else:
             if wsi_name(proto.name):
                 funcs.append('%s' % wsi_ifdef(proto.name))
@@ -1248,25 +1265,34 @@ class APIDumpSubcommand(Subcommand):
             funcs.append('%s%s\n'
                      '{\n'
                      '    using namespace StreamControl;\n'
-                     '    %sinstance_dispatch_table(*pInstance)->%s;\n'
-                     '    if (result == VK_SUCCESS) {\n'
-                     '        createInstanceRegisterExtensions(pCreateInfo, *pInstance);\n'
+                     '    loader_platform_thread_once(&initOnce, initapi_dump);\n'
+                     '    VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);\n'
+                     '    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;\n'
+                     '    PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance) fpGetInstanceProcAddr(NULL, "vkCreateInstance");\n'
+                     '    if (fpCreateInstance == NULL) {\n'
+                     '                return VK_ERROR_INITIALIZATION_FAILED;\n'
                      '    }\n'
+                     '    // Advance the link info for the next element on the chain\n'
+                     '    assert(chain_info->u.pLayerInfo);\n'
+                     '    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;\n'
+                     '    VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);\n'
+                     '    if (result != VK_SUCCESS)\n'
+                     '        return result;\n'
+                     '    initInstanceTable(*pInstance, fpGetInstanceProcAddr);\n'
+                     '    createInstanceRegisterExtensions(pCreateInfo, *pInstance);\n'
                      '    %s%s%s\n'
                      '%s'
-                     '}\n' % (qual, decl, ret_val, proto.c_call(), f_open, log_func, f_close, stmt))
+                     '}\n' % (qual, decl, f_open, log_func, f_close, stmt))
 
         elif proto.name == "CreateDevice":
             funcs.append('%s\n' % self.lineinfo.get())
             funcs.append('%s%s\n'
                      '{\n'
                      '    using namespace StreamControl;\n'
-                     '    %sdevice_dispatch_table(*pDevice)->%s;\n'
-                     '    if (result == VK_SUCCESS)\n'
-                     '        createDeviceRegisterExtensions(pCreateInfo, *pDevice);\n'
+                     '    %sexplicit_CreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);\n'
                      '    %s%s%s\n'
                      '%s'
-                     '}' % (qual, decl, ret_val, proto.c_call(), f_open, log_func, f_close, stmt))
+                     '}' % (qual, decl, ret_val, f_open, log_func, f_close, stmt))
         elif proto.name == "DestroyDevice":
             funcs.append('%s%s\n'
                  '{\n'
@@ -2408,16 +2434,25 @@ class ThreadingSubcommand(Subcommand):
             funcs.append('%s' % self.lineinfo.get())
             funcs.append('%s%s\n' % (qual, decl) +
                      '{\n'
-                     '    VkLayerDispatchTable *pDeviceTable = get_dispatch_table(threading_device_table_map, (void *) *pDevice);\n'
-                     '    VkResult result = pDeviceTable->%s;\n' % (proto.c_call()) +
-                     '    if (result == VK_SUCCESS) {\n'
-                     '        layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(%s), layer_data_map);\n' % proto.params[0].name +
-                     '        layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);\n'
-                     '        my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);\n'
+                     '    VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);\n'
+                     '    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;\n'
+                     '    PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;\n'
+                     '    PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice) fpGetInstanceProcAddr(NULL, "vkCreateDevice");\n'
+                     '    if (fpCreateDevice == NULL) {\n'
+                     '        return VK_ERROR_INITIALIZATION_FAILED;\n'
                      '    }\n'
-                     '\n'
-                     '    return result;'
-                     '}')
+                     '    // Advance the link info for the next element on the chain\n'
+                     '    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;\n'
+                     '    VkResult result = fpCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);\n'
+                     '    if (result != VK_SUCCESS) {\n'
+                     '        return result;\n'
+                     '    }\n'
+                     '    layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);\n'
+                     '    layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);\n'
+                     '    initDeviceTable(*pDevice, fpGetDeviceProcAddr, threading_device_table_map);\n'
+                     '    my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);\n'
+                     '    return result;\n'
+                     '}\n')
             return "\n".join(funcs)
         elif proto.params[0].ty == "VkPhysicalDevice":
             return None
@@ -2473,18 +2508,26 @@ class ThreadingSubcommand(Subcommand):
         elif proto.name == "CreateInstance":
             funcs.append('%s%s\n'
                          '{\n'
-                         '    VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(threading_instance_table_map, *pInstance);\n'
-                         '    VkResult result = pInstanceTable->CreateInstance(pCreateInfo, pAllocator, pInstance);\n'
-                         '\n'
-                         '    if (result == VK_SUCCESS) {\n'
-                         '        layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);\n'
-                         '        my_data->report_data = debug_report_create_instance(\n'
-                         '                                   pInstanceTable,\n'
-                         '                                   *pInstance,\n'
-                         '                                   pCreateInfo->enabledExtensionCount,\n'
-                         '                                   pCreateInfo->ppEnabledExtensionNames);\n'
-                         '        init_threading(my_data, pAllocator);\n'
+                         '    VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);\n'
+                         '    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;\n'
+                         '    PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance) fpGetInstanceProcAddr(NULL, "vkCreateInstance");\n'
+                         '    if (fpCreateInstance == NULL) {\n'
+                         '        return VK_ERROR_INITIALIZATION_FAILED;\n'
+                         '    }\n'
+                         '    // Advance the link info for the next element on the chain\n'
+                         '    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;\n'
+                         '    VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);\n'
+                         '    if (result != VK_SUCCESS) {\n'
+                         '        return result;\n'
                          '    }\n'
+                         '    VkLayerInstanceDispatchTable *pTable = initInstanceTable(*pInstance, fpGetInstanceProcAddr, threading_instance_table_map);\n'
+                         '    layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);\n'
+                         '    my_data->report_data = debug_report_create_instance(\n'
+                         '            pTable,\n'
+                         '            *pInstance,\n'
+                         '            pCreateInfo->enabledExtensionCount,\n'
+                         '            pCreateInfo->ppEnabledExtensionNames);\n'
+                         '    init_threading(my_data, pAllocator);\n'
                          '    return result;\n'
                          '}\n' % (qual, decl))
             return "\n".join(funcs);