loader: Make VkInstance a dispatchable object and init with instance table
diff --git a/include/vkLayer.h b/include/vkLayer.h
index 65656a0..6d1c00d 100644
--- a/include/vkLayer.h
+++ b/include/vkLayer.h
@@ -25,8 +25,8 @@
 
 typedef struct VkLayerDispatchTable_
 {
-    PFN_vkGetProcAddr GetProcAddr;
     PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
+    PFN_vkGetProcAddr GetProcAddr;
     PFN_vkCreateInstance CreateInstance;
     PFN_vkDestroyInstance DestroyInstance;
     PFN_vkEnumeratePhysicalDevices EnumeratePhysicalDevices;
@@ -155,6 +155,24 @@
     PFN_vkQueuePresentWSI QueuePresentWSI;
 } VkLayerDispatchTable;
 
+typedef struct VkLayerInstanceDispatchTable_
+{
+    PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
+    PFN_vkGetProcAddr GetProcAddr;
+    /* non-dispatchable PFN_vkCreateInstance CreateInstance; */
+    PFN_vkDestroyInstance DestroyInstance;
+    PFN_vkEnumeratePhysicalDevices EnumeratePhysicalDevices;
+    PFN_vkGetPhysicalDeviceInfo GetPhysicalDeviceInfo;
+    PFN_vkCreateDevice CreateDevice;
+    /* non-dispatchable PFN_vkGetGlobalExtensionInfo GetGlobalExtensionInfo; */
+    PFN_vkGetPhysicalDeviceExtensionInfo GetPhysicalDeviceExtensionInfo;
+    PFN_vkEnumerateLayers EnumerateLayers;
+    PFN_vkGetMultiDeviceCompatibility GetMultiDeviceCompatibility;
+    PFN_vkDbgRegisterMsgCallback DbgRegisterMsgCallback;
+    PFN_vkDbgUnregisterMsgCallback DbgUnregisterMsgCallback;
+    PFN_vkDbgSetGlobalOption DbgSetGlobalOption;
+} VkLayerInstanceDispatchTable;
+
 // LL node for tree of dbg callback functions
 typedef struct _VK_LAYER_DBG_FUNCTION_NODE
 {
diff --git a/loader/loader.c b/loader/loader.c
index c452ce5..a69801d 100644
--- a/loader/loader.c
+++ b/loader/loader.c
@@ -720,14 +720,6 @@
     loader.layer_scanned = true;
 }
 
-static void loader_init_dispatch_table(VkLayerDispatchTable *tab, PFN_vkGetProcAddr fpGPA, VkPhysicalDevice gpu)
-{
-    loader_initialize_dispatch_table(tab, fpGPA, gpu);
-
-    if (tab->EnumerateLayers == NULL)
-        tab->EnumerateLayers = vkEnumerateLayers;
-}
-
 static void * VKAPI loader_gpa_internal(VkPhysicalDevice gpu, const char * pName)
 {
     if (gpu == VK_NULL_HANDLE) {
@@ -1056,7 +1048,7 @@
             }
 
             if (i == 0) {
-                loader_init_dispatch_table(icd->loader_dispatch + gpu_index, nextGPA, (VkPhysicalDevice) gpuObj);
+                loader_init_device_dispatch_table(icd->loader_dispatch + gpu_index, nextGPA, (VkPhysicalDevice) gpuObj);
                 //Insert the new wrapped objects into the list with loader object at head
                 gpu->nextObject = (VkObject) gpuObj;
                 gpu->pGPA = nextGPA;
@@ -1145,6 +1137,7 @@
         return VK_ERROR_INCOMPATIBLE_DRIVER;
     }
 
+    loader_init_instance_dispatch_table(&ptr_instance->disp);
     *pInstance = (VkInstance) ptr_instance;
     return VK_SUCCESS;
 }
@@ -1255,7 +1248,7 @@
                     (wrapped_gpus + i)->pGPA = get_proc_addr;
                     (wrapped_gpus + i)->nextObject = gpus[i];
                     memcpy(pPhysicalDevices + count, gpus, sizeof(*pPhysicalDevices));
-                    loader_init_dispatch_table(icd->loader_dispatch + i,
+                    loader_init_device_dispatch_table(icd->loader_dispatch + i,
                                                get_proc_addr, gpus[i]);
 
                     /* Verify ICD compatibility */
diff --git a/loader/loader.h b/loader/loader.h
index 89fd912..0a92828 100644
--- a/loader/loader.h
+++ b/loader/loader.h
@@ -64,6 +64,7 @@
 }
 
 struct loader_instance {
+    VkLayerInstanceDispatchTable disp;
     uint32_t total_gpu_count;
     struct loader_icd *icds;
     struct loader_instance *next;
diff --git a/loader/table_ops.h b/loader/table_ops.h
index 37e3774..ca207f9 100644
--- a/loader/table_ops.h
+++ b/loader/table_ops.h
@@ -27,7 +27,7 @@
 #include <string.h>
 #include "loader_platform.h"
 
-static inline void loader_initialize_dispatch_table(VkLayerDispatchTable *table,
+static inline void loader_init_device_dispatch_table(VkLayerDispatchTable *table,
                                                     PFN_vkGetProcAddr gpa,
                                                     VkPhysicalDevice gpu)
 {
@@ -423,3 +423,19 @@
 
     return NULL;
 }
+
+static inline void loader_init_instance_dispatch_table(VkLayerInstanceDispatchTable *table)
+{
+    table->DestroyInstance = vkDestroyInstance;
+    table->EnumeratePhysicalDevices = vkEnumeratePhysicalDevices;
+    table->GetPhysicalDeviceInfo = vkGetPhysicalDeviceInfo;
+    table->GetInstanceProcAddr = vkGetInstanceProcAddr;
+    table->GetProcAddr = vkGetProcAddr;
+    table->CreateDevice = vkCreateDevice;
+    table->GetPhysicalDeviceExtensionInfo = vkGetPhysicalDeviceExtensionInfo;
+    table->EnumerateLayers = vkEnumerateLayers;
+    table->GetMultiDeviceCompatibility = vkGetMultiDeviceCompatibility;
+    table->DbgRegisterMsgCallback = vkDbgRegisterMsgCallback;
+    table->DbgUnregisterMsgCallback = vkDbgUnregisterMsgCallback;
+    table->DbgSetGlobalOption = vkDbgSetGlobalOption;
+}
diff --git a/loader/vk-loader-generate.py b/loader/vk-loader-generate.py
index 8f18ea5..1d55d56 100755
--- a/loader/vk-loader-generate.py
+++ b/loader/vk-loader-generate.py
@@ -237,23 +237,30 @@
                           "#include <string.h>",
                           "#include \"loader_platform.h\""])
 
-    def _generate_init(self):
+    def _generate_init(self, type):
         stmts = []
-        for proto in self.protos:
-            if self.is_dispatchable_object_first_param(proto) or proto.name == "CreateInstance":
-                stmts.append("table->%s = (PFN_vk%s) gpa(gpu, \"vk%s\");" %
-                        (proto.name, proto.name, proto.name))
-            else:
-                stmts.append("table->%s = vk%s; /* non-dispatchable */" %
-                             (proto.name, proto.name))
-
         func = []
-        func.append("static inline void %s_initialize_dispatch_table(VkLayerDispatchTable *table,"
+        if type == "device":
+            for proto in self.protos:
+                if self.is_dispatchable_object_first_param(proto) or proto.name == "CreateInstance":
+                    stmts.append("table->%s = (PFN_vk%s) gpa(gpu, \"vk%s\");" %
+                        (proto.name, proto.name, proto.name))
+                else:
+                    stmts.append("table->%s = vk%s; /* non-dispatchable */" %
+                             (proto.name, proto.name))
+            func.append("static inline void %s_init_device_dispatch_table(VkLayerDispatchTable *table,"
                 % self.prefix)
-        func.append("%s                                              PFN_vkGetProcAddr gpa,"
+            func.append("%s                                              PFN_vkGetProcAddr gpa,"
                 % (" " * len(self.prefix)))
-        func.append("%s                                              VkPhysicalDevice gpu)"
+            func.append("%s                                              VkPhysicalDevice gpu)"
                 % (" " * len(self.prefix)))
+        else:
+            for proto in self.protos:
+                if proto.params[0].ty != "VkInstance" and proto.params[0].ty != "VkPhysicalDevice":
+                    continue
+                stmts.append("table->%s = vk%s;" % (proto.name, proto.name))
+            func.append("static inline void %s_init_instance_dispatch_table(VkLayerInstanceDispatchTable *table)"
+                % self.prefix)
         func.append("{")
         func.append("    %s" % "\n    ".join(stmts))
         func.append("}")
@@ -285,8 +292,9 @@
         return "\n".join(func)
 
     def generate_body(self):
-        body = [self._generate_init(),
-                self._generate_lookup()]
+        body = [self._generate_init("device"),
+                self._generate_lookup(),
+                self._generate_init("instance")]
 
         return "\n\n".join(body)