layers: Add GetInstanceProcAddr() to all layers

Loader will use this for constructing instance layer instance chains.
Layer instance dispatch table is not yet added.
diff --git a/include/vkLayer.h b/include/vkLayer.h
index 6d1c00d..4940726 100644
--- a/include/vkLayer.h
+++ b/include/vkLayer.h
@@ -16,9 +16,10 @@
 #endif
 
 
+typedef void * (*PFN_vkGPA)(VkObject obj, const char * pName);
 typedef struct VkBaseLayerObject_
 {
-    PFN_vkGetProcAddr pGPA;
+    PFN_vkGPA pGPA;
     VkObject nextObject;
     VkObject baseObject;
 } VkBaseLayerObject;
diff --git a/layers/basic.cpp b/layers/basic.cpp
index 260f7c3..e889e31 100644
--- a/layers/basic.cpp
+++ b/layers/basic.cpp
@@ -49,7 +49,7 @@
         return it->second;
     }
 
-    layer_initialize_dispatch_table(pTable, gpuw->pGPA, (VkPhysicalDevice) gpuw->nextObject);
+    layer_initialize_dispatch_table(pTable, (PFN_vkGetProcAddr) gpuw->pGPA, (VkPhysicalDevice) gpuw->nextObject);
 
     return pTable;
 }
@@ -173,20 +173,47 @@
 
     initLayerTable((const VkBaseLayerObject *) gpu);
 
-    if (!strncmp("vkGetProcAddr", pName, sizeof("vkGetProcAddr")))
+    if (!strcmp("vkGetProcAddr", pName))
         return (void *) vkGetProcAddr;
-    else if (!strncmp("vkCreateDevice", pName, sizeof ("vkCreateDevice")))
+    if (!strcmp("vkCreateDevice", pName))
         return (void *) vkCreateDevice;
-    else if (!strncmp("vkEnumerateLayers", pName, sizeof ("vkEnumerateLayers")))
+    if (!strcmp("GetGlobalExtensionInfo", pName))
+        return (void*) vkGetGlobalExtensionInfo;
+    if (!strcmp("vkEnumerateLayers", pName))
         return (void *) vkEnumerateLayers;
-    else if (!strncmp("vkGetFormatInfo", pName, sizeof ("vkGetFormatInfo")))
+    if (!strcmp("vkGetFormatInfo", pName))
         return (void *) vkGetFormatInfo;
-    else if (!strncmp("vkLayerExtension1", pName, sizeof("vkLayerExtension1")))
+    if (!strcmp("vkLayerExtension1", pName))
         return (void *) vkLayerExtension1;
     else {
         VkBaseLayerObject* gpuw = (VkBaseLayerObject *) gpu;
         if (gpuw->pGPA == NULL)
             return NULL;
-        return gpuw->pGPA((VkPhysicalDevice) gpuw->nextObject, pName);
+        return gpuw->pGPA((VkObject) gpuw->nextObject, pName);
+    }
+}
+
+VK_LAYER_EXPORT void * VKAPI vkGetInstanceProcAddr(VkInstance instance, const char* pName)
+{
+    if (instance == NULL)
+        return NULL;
+
+    // TODO initInstanceLayerTable((const VkBaseLayerObject *) instance);
+
+    if (!strcmp("vkGetInstanceProcAddr", pName))
+        return (void *) vkGetInstanceProcAddr;
+    if (!strcmp("vkGetProcAddr", pName))
+        return (void *) vkGetProcAddr;
+    if (!strcmp("GetGlobalExtensionInfo", pName))
+        return (void*) vkGetGlobalExtensionInfo;
+    if (!strcmp("vkCreateDevice", pName))
+        return (void *) vkCreateDevice;
+    if (!strcmp("vkEnumerateLayers", pName))
+        return (void *) vkEnumerateLayers;
+    else {
+        VkBaseLayerObject* instancew = (VkBaseLayerObject *) instance;
+        if (instancew->pGPA == NULL)
+            return NULL;
+        return instancew->pGPA((VkObject) instancew->nextObject, pName);
     }
 }
diff --git a/layers/draw_state.cpp b/layers/draw_state.cpp
index 024df63..95fa1f5 100755
--- a/layers/draw_state.cpp
+++ b/layers/draw_state.cpp
@@ -1458,7 +1458,7 @@
     // initialize Layer dispatch table
     // TODO handle multiple GPUs
     PFN_vkGetProcAddr fpNextGPA;
-    fpNextGPA = pCurObj->pGPA;
+    fpNextGPA = (PFN_vkGetProcAddr) pCurObj->pGPA;
     assert(fpNextGPA);
 
     layer_initialize_dispatch_table(&nextTable, fpNextGPA, (VkPhysicalDevice) pCurObj->nextObject);
@@ -2872,6 +2872,35 @@
     else {
         if (gpuw->pGPA == NULL)
             return NULL;
-        return gpuw->pGPA((VkPhysicalDevice)gpuw->nextObject, funcName);
+        return gpuw->pGPA((VkObject)gpuw->nextObject, funcName);
+    }
+}
+
+VK_LAYER_EXPORT void * VKAPI vkGetInstanceProcAddr(VkInstance instance, const char* funcName)
+{
+    VkBaseLayerObject* instw = (VkBaseLayerObject *) instance;
+    if (instance == NULL)
+        return NULL;
+
+    //TODO
+    //pCurObj = gpuw;
+    //loader_platform_thread_once(&g_initInstanceOnce, initInstanceDrawState);
+
+    if (!strcmp(funcName, "vkGetInstanceProcAddr"))
+        return (void *) vkGetInstanceProcAddr;
+    if (!strcmp(funcName, "vkGetProcAddr"))
+        return (void *) vkGetProcAddr;
+    if (!strcmp(funcName, "vkCreateDevice"))
+        return (void*) vkCreateDevice;
+    if (!strcmp(funcName, "vkEnumerateLayers"))
+        return (void*) vkEnumerateLayers;
+    if (!strcmp(funcName, "vkDbgRegisterMsgCallback"))
+        return (void*) vkDbgRegisterMsgCallback;
+    if (!strcmp(funcName, "vkDbgUnregisterMsgCallback"))
+        return (void*) vkDbgUnregisterMsgCallback;
+    else {
+        if (instw->pGPA == NULL)
+            return NULL;
+        return instw->pGPA((VkObject) instw->nextObject, funcName);
     }
 }
diff --git a/layers/mem_tracker.cpp b/layers/mem_tracker.cpp
index 0a2d61d..2e9307d 100644
--- a/layers/mem_tracker.cpp
+++ b/layers/mem_tracker.cpp
@@ -793,7 +793,7 @@
     // initialize Layer dispatch table
     // TODO handle multiple GPUs
     PFN_vkGetProcAddr fpNextGPA;
-    fpNextGPA = pCurObj->pGPA;
+    fpNextGPA = (PFN_vkGetProcAddr) pCurObj->pGPA;
     assert(fpNextGPA);
 
     layer_initialize_dispatch_table(&nextTable, fpNextGPA, (VkPhysicalDevice) pCurObj->nextObject);
@@ -2156,6 +2156,8 @@
         return (void*) vkCreateDevice;
     if (!strcmp(funcName, "vkDestroyDevice"))
         return (void*) vkDestroyDevice;
+    if (!strcmp(funcName, "GetGlobalExtensionInfo"))
+        return (void*) vkGetGlobalExtensionInfo;
     if (!strcmp(funcName, "vkEnumerateLayers"))
         return (void*) vkEnumerateLayers;
     if (!strcmp(funcName, "vkQueueSubmit"))
@@ -2296,6 +2298,41 @@
         if (gpuw->pGPA == NULL) {
             return NULL;
         }
-        return gpuw->pGPA((VkPhysicalDevice)gpuw->nextObject, funcName);
+        return gpuw->pGPA((VkObject)gpuw->nextObject, funcName);
+    }
+}
+
+VK_LAYER_EXPORT void* VKAPI vkGetInstanceProcAddr(
+    VkInstance       instance,
+    const char       *funcName)
+{
+    VkBaseLayerObject* instw = (VkBaseLayerObject *) instance;
+
+    if (instance == NULL) {
+        return NULL;
+    }
+    //TODO
+    //pCurObj = instw;
+    //loader_platform_thread_once(&g_initInstanceOnce, initInstanceMemTracker);
+
+    if (!strcmp(funcName, "vkGetProcAddr"))
+        return (void *) vkGetProcAddr;
+    if (!strcmp(funcName, "vkGetInstanceProcAddr"))
+        return (void *) vkGetInstanceProcAddr;
+    if (!strcmp(funcName, "vkCreateDevice"))
+        return (void*) vkCreateDevice;
+    if (!strcmp(funcName, "GetGlobalExtensionInfo"))
+        return (void*) vkGetGlobalExtensionInfo;
+    if (!strcmp(funcName, "vkEnumerateLayers"))
+        return (void*) vkEnumerateLayers;
+        if (!strcmp(funcName, "vkDbgRegisterMsgCallback"))
+        return (void*) vkDbgRegisterMsgCallback;
+    if (!strcmp(funcName, "vkDbgUnregisterMsgCallback"))
+        return (void*) vkDbgUnregisterMsgCallback;
+    else {
+        if (instw->pGPA == NULL) {
+            return NULL;
+        }
+        return instw->pGPA((VkObject)instw->nextObject, funcName);
     }
 }
diff --git a/layers/multi.cpp b/layers/multi.cpp
index b26e67d..78ee302 100644
--- a/layers/multi.cpp
+++ b/layers/multi.cpp
@@ -120,18 +120,42 @@
 
     getLayer1Table(gpuw);
 
-    if (!strncmp("vkCreateDevice", pName, sizeof ("vkCreateDevice")))
+    if (!strcmp("vkCreateDevice", pName))
         return (void *) multi1CreateDevice;
-    else if (!strncmp("vkEnumerateLayers", pName, sizeof ("vkEnumerateLayers")))
+    else if (!strcmp("vkEnumerateLayers", pName))
         return (void *) multi1EnumerateLayers;
-    else if (!strncmp("vkCreateGraphicsPipeline", pName, sizeof ("vkCreateGraphicsPipeline")))
+    else if (!strcmp("GetGlobalExtensionInfo", pName))
+        return (void*) vkGetGlobalExtensionInfo;
+    else if (!strcmp("vkCreateGraphicsPipeline", pName))
         return (void *) multi1CreateGraphicsPipeline;
-    else if (!strncmp("vkStorePipeline", pName, sizeof ("vkStorePipeline")))
+    else if (!strcmp("vkStorePipeline", pName))
         return (void *) multi1StorePipeline;
     else {
         if (gpuw->pGPA == NULL)
             return NULL;
-        return gpuw->pGPA((VkPhysicalDevice) gpuw->nextObject, pName);
+        return gpuw->pGPA((VkObject) gpuw->nextObject, pName);
+    }
+}
+
+VK_LAYER_EXPORT void * VKAPI multi1InstanceGetProcAddr(VkInstance inst, const char* pName)
+{
+    VkBaseLayerObject* instw = (VkBaseLayerObject *) inst;
+
+    if (inst == NULL)
+        return NULL;
+
+    //TODO getLayer1InstanceTable(instw);
+
+    if (!strcmp("vkCreateDevice", pName))
+        return (void *) multi1CreateDevice;
+    else if (!strcmp("vkEnumerateLayers", pName))
+        return (void *) multi1EnumerateLayers;
+    else if (!strcmp("GetGlobalExtensionInfo", pName))
+        return (void*) vkGetGlobalExtensionInfo;
+    else {
+        if (instw->pGPA == NULL)
+            return NULL;
+        return instw->pGPA((VkObject) instw->nextObject, pName);
     }
 }
 
@@ -218,18 +242,42 @@
 
     getLayer2Table(gpuw);
 
-    if (!strncmp("vkCreateDevice", pName, sizeof ("vkCreateDevice")))
+    if (!strcmp("vkCreateDevice", pName))
         return (void *) multi2CreateDevice;
-    else if (!strncmp("vkEnumerateLayers", pName, sizeof ("vkEnumerateLayers")))
+    else if (!strcmp("vkEnumerateLayers", pName))
         return (void *) multi2EnumerateLayers;
-    else if (!strncmp("vkCreateCommandBuffer", pName, sizeof ("vkCreateCommandBuffer")))
+    else if (!strcmp("GetGlobalExtensionInfo", pName))
+        return (void*) vkGetGlobalExtensionInfo;
+    else if (!strcmp("vkCreateCommandBuffer", pName))
         return (void *) multi2CreateCommandBuffer;
-    else if (!strncmp("vkBeginCommandBuffer", pName, sizeof ("vkBeginCommandBuffer")))
+    else if (!strcmp("vkBeginCommandBuffer", pName))
         return (void *) multi2BeginCommandBuffer;
     else {
         if (gpuw->pGPA == NULL)
             return NULL;
-        return gpuw->pGPA((VkPhysicalDevice) gpuw->nextObject, pName);
+        return gpuw->pGPA((VkObject) gpuw->nextObject, pName);
+    }
+}
+
+VK_LAYER_EXPORT void * VKAPI multi2InstanceGetProcAddr(VkInstance inst, const char* pName)
+{
+    VkBaseLayerObject* instw = (VkBaseLayerObject *) inst;
+
+    if (inst == NULL)
+        return NULL;
+
+    //TODO getLayer2InstanceTable(instw);
+
+    if (!strcmp("vkCreateDevice", pName))
+        return (void *) multi2CreateDevice;
+    else if (!strcmp("vkEnumerateLayers", pName))
+        return (void *) multi2EnumerateLayers;
+    else if (!strcmp("GetGlobalExtensionInfo", pName))
+        return (void*) vkGetGlobalExtensionInfo;
+    else {
+        if (instw->pGPA == NULL)
+            return NULL;
+        return instw->pGPA((VkObject) instw->nextObject, pName);
     }
 }
 
@@ -304,11 +352,11 @@
 VK_LAYER_EXPORT void * VKAPI vkGetProcAddr(VkPhysicalDevice gpu, const char* pName)
 {
     // to find each layers GPA routine Loader will search via "<layerName>GetProcAddr"
-    if (!strncmp("multi1GetProcAddr", pName, sizeof("multi1GetProcAddr")))
+    if (!strcmp("multi1GetProcAddr", pName))
         return (void *) multi1GetProcAddr;
-    else if (!strncmp("multi2GetProcAddr", pName, sizeof("multi2GetProcAddr")))
+    else if (!strcmp("multi2GetProcAddr", pName))
         return (void *) multi2GetProcAddr;
-    else if (!strncmp("vkGetProcAddr", pName, sizeof("vkGetProcAddr")))
+    else if (!strcmp("vkGetProcAddr", pName))
         return (void *) vkGetProcAddr;
 
     // use first layer activated as GPA dispatch table activation happens in order
@@ -321,6 +369,31 @@
 
 }
 
+VK_LAYER_EXPORT void * VKAPI vkGetInstanceProcAddr(VkInstance inst, const char* pName)
+{
+    // to find each layers GPA routine Loader will search via "<layerName>GetProcAddr"
+    if (!strcmp("multi1GetProcAddr", pName))
+        return (void *) multi1GetProcAddr;
+    else if (!strcmp("multi2GetProcAddr", pName))
+        return (void *) multi2GetProcAddr;
+    else if (!strcmp("vkGetProcAddr", pName))
+        return (void *) vkGetProcAddr;
+    else if (!strcmp("multi1GetInstanceProcAddr", pName))
+        return (void *) multi1GetProcAddr;
+    else if (!strcmp("multi2GetInstanceProcAddr", pName))
+        return (void *) multi2GetProcAddr;
+    else if (!strcmp("vkGetInstanceProcAddr", pName))
+        return (void *) vkGetProcAddr;
+
+    // use first layer activated as GPA dispatch table activation happens in order
+    else if (layer1_first_activated)
+        return multi1InstanceGetProcAddr(inst, pName);
+    else if (layer2_first_activated)
+        return multi2InstanceGetProcAddr(inst, pName);
+    else
+        return NULL;
+
+}
 #ifdef __cplusplus
 }    //extern "C"
 #endif
@@ -332,5 +405,5 @@
     if (layerNum == 1 && layer2_first_activated == false)
         layer1_first_activated = true;
 
-    layer_initialize_dispatch_table(pTable, gpuw->pGPA, (VkPhysicalDevice) gpuw->nextObject);
+    layer_initialize_dispatch_table(pTable, (PFN_vkGetProcAddr) gpuw->pGPA, (VkPhysicalDevice) gpuw->nextObject);
 }
diff --git a/layers/param_checker.cpp b/layers/param_checker.cpp
index f91518d..a63e4a9 100644
--- a/layers/param_checker.cpp
+++ b/layers/param_checker.cpp
@@ -65,7 +65,7 @@
     }
 
     PFN_vkGetProcAddr fpNextGPA;
-    fpNextGPA = pCurObj->pGPA;
+    fpNextGPA = (PFN_vkGetProcAddr) pCurObj->pGPA;
     assert(fpNextGPA);
 
     layer_initialize_dispatch_table(&nextTable, fpNextGPA, (VkPhysicalDevice) pCurObj->nextObject);
@@ -1953,7 +1953,296 @@
     return result;
 }
 
-#include "vk_generic_intercept_proc_helper.h"
+static inline void* layer_intercept_proc(const char *name)
+{
+    if (!name || name[0] != 'v' || name[1] != 'k')
+        return NULL;
+
+    name += 2;
+    if (!strcmp(name, "CreateInstance"))
+        return (void*) vkCreateInstance;
+    if (!strcmp(name, "DestroyInstance"))
+        return (void*) vkDestroyInstance;
+    if (!strcmp(name, "GetPhysicalDeviceInfo"))
+        return (void*) vkGetPhysicalDeviceInfo;
+    if (!strcmp(name, "GetProcAddr"))
+        return (void*) vkGetProcAddr;
+    if (!strcmp(name, "CreateDevice"))
+        return (void*) vkCreateDevice;
+    if (!strcmp(name, "DestroyDevice"))
+        return (void*) vkDestroyDevice;
+    if (!strcmp(name, "GetGlobalExtensionInfo"))
+        return (void*) vkGetGlobalExtensionInfo;
+    if (!strcmp(name, "GetPhysicalDeviceExtensionInfo"))
+        return (void*) vkGetPhysicalDeviceExtensionInfo;
+    if (!strcmp(name, "EnumerateLayers"))
+        return (void*) vkEnumerateLayers;
+    if (!strcmp(name, "GetDeviceQueue"))
+        return (void*) vkGetDeviceQueue;
+    if (!strcmp(name, "QueueSubmit"))
+        return (void*) vkQueueSubmit;
+    if (!strcmp(name, "QueueWaitIdle"))
+        return (void*) vkQueueWaitIdle;
+    if (!strcmp(name, "DeviceWaitIdle"))
+        return (void*) vkDeviceWaitIdle;
+    if (!strcmp(name, "AllocMemory"))
+        return (void*) vkAllocMemory;
+    if (!strcmp(name, "FreeMemory"))
+        return (void*) vkFreeMemory;
+    if (!strcmp(name, "SetMemoryPriority"))
+        return (void*) vkSetMemoryPriority;
+    if (!strcmp(name, "MapMemory"))
+        return (void*) vkMapMemory;
+    if (!strcmp(name, "UnmapMemory"))
+        return (void*) vkUnmapMemory;
+    if (!strcmp(name, "FlushMappedMemoryRanges"))
+        return (void*) vkFlushMappedMemoryRanges;
+    if (!strcmp(name, "InvalidateMappedMemoryRanges"))
+        return (void*) vkInvalidateMappedMemoryRanges;
+    if (!strcmp(name, "PinSystemMemory"))
+        return (void*) vkPinSystemMemory;
+    if (!strcmp(name, "GetMultiDeviceCompatibility"))
+        return (void*) vkGetMultiDeviceCompatibility;
+    if (!strcmp(name, "OpenSharedMemory"))
+        return (void*) vkOpenSharedMemory;
+    if (!strcmp(name, "OpenSharedSemaphore"))
+        return (void*) vkOpenSharedSemaphore;
+    if (!strcmp(name, "OpenPeerMemory"))
+        return (void*) vkOpenPeerMemory;
+    if (!strcmp(name, "OpenPeerImage"))
+        return (void*) vkOpenPeerImage;
+    if (!strcmp(name, "DestroyObject"))
+        return (void*) vkDestroyObject;
+    if (!strcmp(name, "GetObjectInfo"))
+        return (void*) vkGetObjectInfo;
+    if (!strcmp(name, "CreateFence"))
+        return (void*) vkCreateFence;
+    if (!strcmp(name, "ResetFences"))
+        return (void*) vkResetFences;
+    if (!strcmp(name, "GetFenceStatus"))
+        return (void*) vkGetFenceStatus;
+    if (!strcmp(name, "WaitForFences"))
+        return (void*) vkWaitForFences;
+    if (!strcmp(name, "CreateSemaphore"))
+        return (void*) vkCreateSemaphore;
+    if (!strcmp(name, "QueueSignalSemaphore"))
+        return (void*) vkQueueSignalSemaphore;
+    if (!strcmp(name, "QueueWaitSemaphore"))
+        return (void*) vkQueueWaitSemaphore;
+    if (!strcmp(name, "CreateEvent"))
+        return (void*) vkCreateEvent;
+    if (!strcmp(name, "GetEventStatus"))
+        return (void*) vkGetEventStatus;
+    if (!strcmp(name, "SetEvent"))
+        return (void*) vkSetEvent;
+    if (!strcmp(name, "ResetEvent"))
+        return (void*) vkResetEvent;
+    if (!strcmp(name, "CreateQueryPool"))
+        return (void*) vkCreateQueryPool;
+    if (!strcmp(name, "GetQueryPoolResults"))
+        return (void*) vkGetQueryPoolResults;
+    if (!strcmp(name, "GetFormatInfo"))
+        return (void*) vkGetFormatInfo;
+    if (!strcmp(name, "CreateBuffer"))
+        return (void*) vkCreateBuffer;
+    if (!strcmp(name, "CreateBufferView"))
+        return (void*) vkCreateBufferView;
+    if (!strcmp(name, "CreateImage"))
+        return (void*) vkCreateImage;
+    if (!strcmp(name, "GetImageSubresourceInfo"))
+        return (void*) vkGetImageSubresourceInfo;
+    if (!strcmp(name, "CreateImageView"))
+        return (void*) vkCreateImageView;
+    if (!strcmp(name, "CreateColorAttachmentView"))
+        return (void*) vkCreateColorAttachmentView;
+    if (!strcmp(name, "CreateDepthStencilView"))
+        return (void*) vkCreateDepthStencilView;
+    if (!strcmp(name, "CreateShader"))
+        return (void*) vkCreateShader;
+    if (!strcmp(name, "CreateGraphicsPipeline"))
+        return (void*) vkCreateGraphicsPipeline;
+    if (!strcmp(name, "CreateGraphicsPipelineDerivative"))
+        return (void*) vkCreateGraphicsPipelineDerivative;
+    if (!strcmp(name, "CreateComputePipeline"))
+        return (void*) vkCreateComputePipeline;
+    if (!strcmp(name, "StorePipeline"))
+        return (void*) vkStorePipeline;
+    if (!strcmp(name, "LoadPipeline"))
+        return (void*) vkLoadPipeline;
+    if (!strcmp(name, "LoadPipelineDerivative"))
+        return (void*) vkLoadPipelineDerivative;
+    if (!strcmp(name, "CreatePipelineLayout"))
+        return (void*) vkCreatePipelineLayout;
+    if (!strcmp(name, "CreateSampler"))
+        return (void*) vkCreateSampler;
+    if (!strcmp(name, "CreateDescriptorSetLayout"))
+        return (void*) vkCreateDescriptorSetLayout;
+    if (!strcmp(name, "CreateDescriptorPool"))
+        return (void*) vkCreateDescriptorPool;
+    if (!strcmp(name, "ResetDescriptorPool"))
+        return (void*) vkResetDescriptorPool;
+    if (!strcmp(name, "AllocDescriptorSets"))
+        return (void*) vkAllocDescriptorSets;
+    if (!strcmp(name, "ClearDescriptorSets"))
+        return (void*) vkClearDescriptorSets;
+    if (!strcmp(name, "CreateDynamicViewportState"))
+        return (void*) vkCreateDynamicViewportState;
+    if (!strcmp(name, "CreateDynamicRasterState"))
+        return (void*) vkCreateDynamicRasterState;
+    if (!strcmp(name, "CreateDynamicColorBlendState"))
+        return (void*) vkCreateDynamicColorBlendState;
+    if (!strcmp(name, "CreateDynamicDepthStencilState"))
+        return (void*) vkCreateDynamicDepthStencilState;
+    if (!strcmp(name, "CreateCommandBuffer"))
+        return (void*) vkCreateCommandBuffer;
+    if (!strcmp(name, "BeginCommandBuffer"))
+        return (void*) vkBeginCommandBuffer;
+    if (!strcmp(name, "EndCommandBuffer"))
+        return (void*) vkEndCommandBuffer;
+    if (!strcmp(name, "ResetCommandBuffer"))
+        return (void*) vkResetCommandBuffer;
+    if (!strcmp(name, "CmdBindPipeline"))
+        return (void*) vkCmdBindPipeline;
+    if (!strcmp(name, "CmdBindDynamicStateObject"))
+        return (void*) vkCmdBindDynamicStateObject;
+    if (!strcmp(name, "CmdBindDescriptorSets"))
+        return (void*) vkCmdBindDescriptorSets;
+    if (!strcmp(name, "CmdBindVertexBuffers"))
+        return (void*) vkCmdBindVertexBuffers;
+    if (!strcmp(name, "CmdBindIndexBuffer"))
+        return (void*) vkCmdBindIndexBuffer;
+    if (!strcmp(name, "CmdDraw"))
+        return (void*) vkCmdDraw;
+    if (!strcmp(name, "CmdDrawIndexed"))
+        return (void*) vkCmdDrawIndexed;
+    if (!strcmp(name, "CmdDrawIndirect"))
+        return (void*) vkCmdDrawIndirect;
+    if (!strcmp(name, "CmdDrawIndexedIndirect"))
+        return (void*) vkCmdDrawIndexedIndirect;
+    if (!strcmp(name, "CmdDispatch"))
+        return (void*) vkCmdDispatch;
+    if (!strcmp(name, "CmdDispatchIndirect"))
+        return (void*) vkCmdDispatchIndirect;
+    if (!strcmp(name, "CmdCopyBuffer"))
+        return (void*) vkCmdCopyBuffer;
+    if (!strcmp(name, "CmdCopyImage"))
+        return (void*) vkCmdCopyImage;
+    if (!strcmp(name, "CmdBlitImage"))
+        return (void*) vkCmdBlitImage;
+    if (!strcmp(name, "CmdCopyBufferToImage"))
+        return (void*) vkCmdCopyBufferToImage;
+    if (!strcmp(name, "CmdCopyImageToBuffer"))
+        return (void*) vkCmdCopyImageToBuffer;
+    if (!strcmp(name, "CmdUpdateBuffer"))
+        return (void*) vkCmdUpdateBuffer;
+    if (!strcmp(name, "CmdFillBuffer"))
+        return (void*) vkCmdFillBuffer;
+    if (!strcmp(name, "CmdClearColorImage"))
+        return (void*) vkCmdClearColorImage;
+    if (!strcmp(name, "CmdClearDepthStencil"))
+        return (void*) vkCmdClearDepthStencil;
+    if (!strcmp(name, "CmdResolveImage"))
+        return (void*) vkCmdResolveImage;
+    if (!strcmp(name, "CmdSetEvent"))
+        return (void*) vkCmdSetEvent;
+    if (!strcmp(name, "CmdResetEvent"))
+        return (void*) vkCmdResetEvent;
+    if (!strcmp(name, "CmdWaitEvents"))
+        return (void*) vkCmdWaitEvents;
+    if (!strcmp(name, "CmdPipelineBarrier"))
+        return (void*) vkCmdPipelineBarrier;
+    if (!strcmp(name, "CmdBeginQuery"))
+        return (void*) vkCmdBeginQuery;
+    if (!strcmp(name, "CmdEndQuery"))
+        return (void*) vkCmdEndQuery;
+    if (!strcmp(name, "CmdResetQueryPool"))
+        return (void*) vkCmdResetQueryPool;
+    if (!strcmp(name, "CmdWriteTimestamp"))
+        return (void*) vkCmdWriteTimestamp;
+    if (!strcmp(name, "CmdCopyQueryPoolResults"))
+        return (void*) vkCmdCopyQueryPoolResults;
+    if (!strcmp(name, "CmdInitAtomicCounters"))
+        return (void*) vkCmdInitAtomicCounters;
+    if (!strcmp(name, "CmdLoadAtomicCounters"))
+        return (void*) vkCmdLoadAtomicCounters;
+    if (!strcmp(name, "CmdSaveAtomicCounters"))
+        return (void*) vkCmdSaveAtomicCounters;
+    if (!strcmp(name, "CreateFramebuffer"))
+        return (void*) vkCreateFramebuffer;
+    if (!strcmp(name, "CreateRenderPass"))
+        return (void*) vkCreateRenderPass;
+    if (!strcmp(name, "CmdBeginRenderPass"))
+        return (void*) vkCmdBeginRenderPass;
+    if (!strcmp(name, "CmdEndRenderPass"))
+        return (void*) vkCmdEndRenderPass;
+    if (!strcmp(name, "DbgSetValidationLevel"))
+        return (void*) vkDbgSetValidationLevel;
+    if (!strcmp(name, "DbgRegisterMsgCallback"))
+        return (void*) vkDbgRegisterMsgCallback;
+    if (!strcmp(name, "DbgUnregisterMsgCallback"))
+        return (void*) vkDbgUnregisterMsgCallback;
+    if (!strcmp(name, "DbgSetMessageFilter"))
+        return (void*) vkDbgSetMessageFilter;
+    if (!strcmp(name, "DbgSetObjectTag"))
+        return (void*) vkDbgSetObjectTag;
+    if (!strcmp(name, "DbgSetGlobalOption"))
+        return (void*) vkDbgSetGlobalOption;
+    if (!strcmp(name, "DbgSetDeviceOption"))
+        return (void*) vkDbgSetDeviceOption;
+    if (!strcmp(name, "CmdDbgMarkerBegin"))
+        return (void*) vkCmdDbgMarkerBegin;
+    if (!strcmp(name, "CmdDbgMarkerEnd"))
+        return (void*) vkCmdDbgMarkerEnd;
+    if (!strcmp(name, "GetDisplayInfoWSI"))
+        return (void*) vkGetDisplayInfoWSI;
+    if (!strcmp(name, "CreateSwapChainWSI"))
+        return (void*) vkCreateSwapChainWSI;
+    if (!strcmp(name, "DestroySwapChainWSI"))
+        return (void*) vkDestroySwapChainWSI;
+    if (!strcmp(name, "GetSwapChainInfoWSI"))
+        return (void*) vkGetSwapChainInfoWSI;
+    if (!strcmp(name, "QueuePresentWSI"))
+        return (void*) vkQueuePresentWSI;
+
+    return NULL;
+}
+
+static inline void* layer_intercept_instance_proc(const char *name)
+{
+    if (!name || name[0] != 'v' || name[1] != 'k')
+        return NULL;
+
+    name += 2;
+    if (!strcmp(name, "GetInstanceProcAddr"))
+        return (void*) vkGetInstanceProcAddr;
+    if (!strcmp(name, "CreateInstance"))
+        return (void*) vkCreateInstance;
+    if (!strcmp(name, "DestroyInstance"))
+        return (void*) vkDestroyInstance;
+    if (!strcmp(name, "GetPhysicalDeviceInfo"))
+        return (void*) vkGetPhysicalDeviceInfo;
+    if (!strcmp(name, "GetProcAddr"))
+        return (void*) vkGetProcAddr;
+    if (!strcmp(name, "CreateDevice"))
+        return (void*) vkCreateDevice;
+    if (!strcmp(name, "GetGlobalExtensionInfo"))
+        return (void*) vkGetGlobalExtensionInfo;
+    if (!strcmp(name, "GetPhysicalDeviceExtensionInfo"))
+        return (void*) vkGetPhysicalDeviceExtensionInfo;
+    if (!strcmp(name, "EnumerateLayers"))
+        return (void*) vkEnumerateLayers;
+    if (!strcmp(name, "GetMultiDeviceCompatibility"))
+        return (void*) vkGetMultiDeviceCompatibility;
+    if (!strcmp(name, "DbgRegisterMsgCallback"))
+        return (void*) vkDbgRegisterMsgCallback;
+    if (!strcmp(name, "DbgUnregisterMsgCallback"))
+        return (void*) vkDbgUnregisterMsgCallback;
+    if (!strcmp(name, "DbgSetGlobalOption"))
+        return (void*) vkDbgSetGlobalOption;
+
+    return NULL;
+}
+
 VK_LAYER_EXPORT void* VKAPI vkGetProcAddr(VkPhysicalDevice gpu, const char* funcName)
 {
     VkBaseLayerObject* gpuw = (VkBaseLayerObject *) gpu;
@@ -1969,7 +2258,25 @@
     else {
         if (gpuw->pGPA == NULL)
             return NULL;
-        return gpuw->pGPA((VkPhysicalDevice)gpuw->nextObject, funcName);
+        return gpuw->pGPA((VkObject)gpuw->nextObject, funcName);
     }
 }
 
+VK_LAYER_EXPORT void* VKAPI vkGetInstanceProcAddr(VkInstance inst, const char* funcName)
+{
+    VkBaseLayerObject* instw = (VkBaseLayerObject *) inst;
+    void* addr;
+    if (inst == NULL)
+        return NULL;
+    //TODO pCurObj = instw;
+    //TODO loader_platform_thread_once(&tabOnce, initParamChecker);
+
+    addr = layer_intercept_instance_proc(funcName);
+    if (addr)
+        return addr;
+    else {
+        if (instw->pGPA == NULL)
+            return NULL;
+        return instw->pGPA((VkObject)instw->nextObject, funcName);
+    }
+}
diff --git a/layers/shader_checker.cpp b/layers/shader_checker.cpp
index a576314..f36fee3 100644
--- a/layers/shader_checker.cpp
+++ b/layers/shader_checker.cpp
@@ -159,8 +159,7 @@
         return it->second;
     }
 
-    layer_initialize_dispatch_table(pTable, gpuw->pGPA, (VkPhysicalDevice) gpuw->nextObject);
-    pCurObj = (VkBaseLayerObject *)gpuw->baseObject;
+    layer_initialize_dispatch_table(pTable, (PFN_vkGetProcAddr) gpuw->pGPA, (VkPhysicalDevice) gpuw->nextObject);
 
     return pTable;
 }
@@ -1011,6 +1010,7 @@
 
     ADD_HOOK(vkGetProcAddr);
     ADD_HOOK(vkEnumerateLayers);
+    ADD_HOOK(vkGetGlobalExtensionInfo);
     ADD_HOOK(vkCreateDevice);
     ADD_HOOK(vkCreateShader);
     ADD_HOOK(vkCreateGraphicsPipeline);
@@ -1021,5 +1021,30 @@
     VkBaseLayerObject* gpuw = (VkBaseLayerObject *) gpu;
     if (gpuw->pGPA == NULL)
         return NULL;
-    return gpuw->pGPA((VkPhysicalDevice) gpuw->nextObject, pName);
+    return gpuw->pGPA((VkObject) gpuw->nextObject, pName);
+}
+
+VK_LAYER_EXPORT void * VKAPI vkGetInstanceProcAddr(VkInstance inst, const char* pName)
+{
+    if (inst == NULL)
+        return NULL;
+
+    //TODO initLayerTable((const VkBaseLayerObject *) inst);
+
+    // TODO loader_platform_thread_once(&g_initOnce, initInstanceLayer);
+
+#define ADD_HOOK(fn)    \
+    if (!strncmp(#fn, pName, sizeof(#fn))) \
+        return (void *) fn
+
+    ADD_HOOK(vkGetProcAddr);
+    ADD_HOOK(vkGetInstanceProcAddr);
+    ADD_HOOK(vkEnumerateLayers);
+    ADD_HOOK(vkGetGlobalExtensionInfo);
+    ADD_HOOK(vkCreateDevice);
+
+    VkBaseLayerObject* instw = (VkBaseLayerObject *) inst;
+    if (instw->pGPA == NULL)
+        return NULL;
+    return instw->pGPA((VkObject) instw->nextObject, pName);
 }
diff --git a/vk-layer-generate.py b/vk-layer-generate.py
index b61890a..0311209 100755
--- a/vk-layer-generate.py
+++ b/vk-layer-generate.py
@@ -280,7 +280,7 @@
         funcs = []
         intercepted = []
         for proto in self.protos:
-            if proto.name == "GetProcAddr":
+            if proto.name == "GetProcAddr" or proto.name == "GetInstanceProcAddr":
                 intercepted.append(proto)
             else:
                 intercept = self.generate_intercept(proto, qual)
@@ -314,6 +314,27 @@
         body.append("")
         body.append("    return NULL;")
         body.append("}")
+        # add layer_intercept_instance_proc
+        lookups = []
+        for proto in self.protos:
+            if proto.params[0].ty != "VkInstance" and proto.params[0].ty != "VkPhysicalDevice" and proto.name != "CreateInstance" and proto.name != "GetGlobalExtensionInfo":
+                continue
+
+            if not proto in intercepted:
+                continue
+            lookups.append("if (!strcmp(name, \"%s\"))" % proto.name)
+            lookups.append("    return (void*) %s%s;" % (prefix, proto.name))
+
+        body.append("static inline void* layer_intercept_instance_proc(const char *name)")
+        body.append("{")
+        body.append(generate_get_proc_addr_check("name"))
+        body.append("")
+        body.append("    name += 2;")
+        body.append("    %s" % "\n    ".join(lookups))
+        body.append("")
+        body.append("    return NULL;")
+        body.append("}")
+
         funcs.append("\n".join(body))
         return "\n\n".join(funcs)
 
@@ -381,7 +402,7 @@
         exts.append('}')
         return "\n".join(exts)
 
-    def _generate_layer_gpa_function(self, extensions=[]):
+    def _generate_layer_gpa_function(self, extensions=[], instance_extensions=[]):
         func_body = []
         func_body.append("VK_LAYER_EXPORT void* VKAPI vkGetProcAddr(VkPhysicalDevice gpu, const char* funcName)\n"
                          "{\n"
@@ -402,12 +423,39 @@
                 cpp_prefix = "reinterpret_cast<void*>("
                 cpp_postfix = ")"
             for ext_name in extensions:
+#<<<<<<< HEAD
                 func_body.append('    else if (!strncmp("%s", funcName, sizeof("%s")))\n'
                                  '        return %s%s%s;' % (ext_name, ext_name, cpp_prefix, ext_name, cpp_postfix))
+#=======
+#                func_body.append('    else if (!strcmp("%s", funcName))\n'
+#                                 '        return %s;' % (ext_name, ext_name))
+#>>>>>>> layers: Add GetInstanceProcAddr() to all layers
         func_body.append("    else {\n"
                          "        if (gpuw->pGPA == NULL)\n"
                          "            return NULL;\n"
-                         "        return gpuw->pGPA((VkPhysicalDevice)gpuw->nextObject, funcName);\n"
+                         "        return gpuw->pGPA((VkObject)gpuw->nextObject, funcName);\n"
+                         "    }\n"
+                         "}\n")
+        func_body.append("VK_LAYER_EXPORT void* VKAPI vkGetInstanceProcAddr(VkInstance inst, const char* funcName)\n"
+                         "{\n"
+                         "    VkBaseLayerObject* instw = (VkBaseLayerObject *) inst;\n"
+                         "    void* addr;\n"
+                         "    if (inst == VK_NULL_HANDLE)\n"
+                         "        return NULL;\n"
+                         "    // TODO pCurObj = instw;\n"
+                         "    // TODO loader_platform_thread_once(&tabInstanceOnce, initInstance%s);\n\n"
+                         "    addr = layer_intercept_instance_proc(funcName);\n"
+                         "    if (addr)\n"
+                         "        return addr;" % self.layer_name)
+
+        if 0 != len(instance_extensions):
+            for ext_name in instance_extensions:
+                func_body.append('    else if (!strcmp("%s", funcName))\n'
+                                 '        return %s;' % (ext_name, ext_name))
+        func_body.append("    else {\n"
+                         "        if (instw->pGPA == NULL)\n"
+                         "            return NULL;\n"
+                         "        return instw->pGPA((VkObject)instw->nextObject, funcName);\n"
                          "    }\n"
                          "}\n")
         return "\n".join(func_body)
@@ -434,7 +482,7 @@
             func_body.append('    }')
             func_body.append('')
         func_body.append('    PFN_vkGetProcAddr fpNextGPA;\n'
-                         '    fpNextGPA = pCurObj->pGPA;\n'
+                         '    fpNextGPA = (PFN_vkGetProcAddr) pCurObj->pGPA;\n'
                          '    assert(fpNextGPA);\n')
 
         func_body.append("    layer_initialize_dispatch_table(&nextTable, fpNextGPA, (VkPhysicalDevice) pCurObj->nextObject);")
@@ -650,7 +698,7 @@
         func_body.append('    ConfigureOutputStream(writeToFile, flushAfterWrite);')
         func_body.append('')
         func_body.append('    PFN_vkGetProcAddr fpNextGPA;')
-        func_body.append('    fpNextGPA = pCurObj->pGPA;')
+        func_body.append('    fpNextGPA = (PFN_vkGetProcAddr) pCurObj->pGPA;')
         func_body.append('    assert(fpNextGPA);')
         func_body.append('    layer_initialize_dispatch_table(&nextTable, fpNextGPA, (VkPhysicalDevice) pCurObj->nextObject);')
         func_body.append('')