loader: implement new layer init method

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
diff --git a/layers/api_dump.h b/layers/api_dump.h
index 3dc8e2f..73c6a49 100644
--- a/layers/api_dump.h
+++ b/layers/api_dump.h
@@ -125,3 +125,34 @@
     }
 }
 
+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;
+}
diff --git a/layers/basic.cpp b/layers/basic.cpp
index 77b08c0..45cb999 100644
--- a/layers/basic.cpp
+++ b/layers/basic.cpp
@@ -95,6 +95,32 @@
     }
 }
 
+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 @@
     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 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);
diff --git a/layers/device_limits.cpp b/layers/device_limits.cpp
index fbb9af3..24df64e 100644
--- a/layers/device_limits.cpp
+++ b/layers/device_limits.cpp
@@ -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 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);
+    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);
-
-        init_device_limits(my_data, pAllocator);
-        my_data->instanceState = unique_ptr<INSTANCE_STATE>(new INSTANCE_STATE());
+    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 @@
     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 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 @@
     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 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 @@
     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;
diff --git a/layers/draw_state.cpp b/layers/draw_state.cpp
index c85598d..8d6ac65 100644
--- a/layers/draw_state.cpp
+++ b/layers/draw_state.cpp
@@ -2813,21 +2813,34 @@
 
 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance)
 {
-    // TODOSC : Shouldn't need any customization here
-    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) {
-        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);
-
-        init_draw_state(my_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);
+    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_draw_state(my_data, pAllocator);
+
     return result;
 }
 
@@ -2890,16 +2903,35 @@
 
 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 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 @@
     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 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 @@
     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);
 }
diff --git a/layers/image.cpp b/layers/image.cpp
index 1281dfb..f371bdc 100644
--- a/layers/image.cpp
+++ b/layers/image.cpp
@@ -146,16 +146,34 @@
 
 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);
+    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);
-
-        InitImage(my_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);
+    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);
+
+    InitImage(my_data, pAllocator);
+
     return result;
 }
 
@@ -182,16 +200,35 @@
 
 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;
     }
 
-    instance_data->instance_dispatch_table->GetPhysicalDeviceProperties(physicalDevice, &(device_data->physicalDeviceProperties));
+    // 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);
+    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 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 @@
     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 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 @@
     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);
 }
diff --git a/layers/mem_tracker.cpp b/layers/mem_tracker.cpp
index b621c6e..afcc7cd 100644
--- a/layers/mem_tracker.cpp
+++ b/layers/mem_tracker.cpp
@@ -1119,19 +1119,35 @@
     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);
-
-        init_mem_tracker(my_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);
+    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 @@
     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 @@
     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 @@
         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 @@
     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 @@
     if (!strcmp(funcName, "vkEnumerateDeviceExtensionProperties"))
         return (PFN_vkVoidFunction) vkEnumerateDeviceExtensionProperties;
 
-    fptr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);
-    if (fptr)
-        return fptr;
+    if (instance == NULL) return NULL;
 
-    {
-        VkLayerInstanceDispatchTable* pTable = my_data->instance_dispatch_table;
-        if (pTable->GetInstanceProcAddr == NULL)
-            return NULL;
-        return pTable->GetInstanceProcAddr(instance, funcName);
-    }
+    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);
 }
diff --git a/layers/multi.cpp b/layers/multi.cpp
index c5d9d1b..3bbea8c 100644
--- a/layers/multi.cpp
+++ b/layers/multi.cpp
@@ -80,28 +80,22 @@
 
 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 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 @@
         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
diff --git a/layers/object_tracker.h b/layers/object_tracker.h
index de44f0e..4622c18 100644
--- a/layers/object_tracker.h
+++ b/layers/object_tracker.h
@@ -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 @@
     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);
-
-    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);
+    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);
+    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 @@
     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;
 }
diff --git a/layers/param_checker.cpp b/layers/param_checker.cpp
index c351837..f63562d 100644
--- a/layers/param_checker.cpp
+++ b/layers/param_checker.cpp
@@ -1760,18 +1760,34 @@
     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 @@
     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 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 @@
     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 @@
     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);
 }
diff --git a/layers/screenshot.cpp b/layers/screenshot.cpp
index 521aedc..3231289 100644
--- a/layers/screenshot.cpp
+++ b/layers/screenshot.cpp
@@ -406,21 +406,36 @@
     const VkAllocationCallbacks* pAllocator,
     VkDevice                 *pDevice)
 {
-    VkLayerDispatchTable *pDisp  = get_dispatch_table(screenshot_device_table_map, *pDevice);
-    VkResult result = pDisp->CreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
+    VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
 
-    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;
+    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 @@
     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 @@
     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 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;
diff --git a/layers/swapchain.cpp b/layers/swapchain.cpp
index d9e0a09..051d14f 100644
--- a/layers/swapchain.cpp
+++ b/layers/swapchain.cpp
@@ -286,22 +286,37 @@
 
 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 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 @@
     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 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 @@
         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);
diff --git a/layers/unique_objects.h b/layers/unique_objects.h
index 02e6699..8d344a0 100644
--- a/layers/unique_objects.h
+++ b/layers/unique_objects.h
@@ -141,13 +141,27 @@
     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);
-
-    if (result == VK_SUCCESS) {
-        createInstanceRegisterExtensions(pCreateInfo, *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;
+
+    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 @@
     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;
 }
 
diff --git a/layers/vk_layer_table.cpp b/layers/vk_layer_table.cpp
index 93d2fbf..b06fb31 100644
--- a/layers/vk_layer_table.cpp
+++ b/layers/vk_layer_table.cpp
@@ -100,9 +100,9 @@
     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 @@
     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 @@
  *    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);
 }
diff --git a/layers/vk_layer_table.h b/layers/vk_layer_table.h
index 04ea266..0011c85 100644
--- a/layers/vk_layer_table.h
+++ b/layers/vk_layer_table.h
@@ -29,10 +29,11 @@
 
 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 @@
 
 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);