loader: Add support for debug report
diff --git a/layers/layers_msg.h b/layers/layers_msg.h
index 88208f9..a5e90de 100644
--- a/layers/layers_msg.h
+++ b/layers/layers_msg.h
@@ -62,6 +62,8 @@
         pNewDbgFuncNode->msgFlags = msgFlags;
         pNewDbgFuncNode->pUserData = pUserData;
         pNewDbgFuncNode->pNext = g_pDbgFunctionHead;
+
+        /* TODO: This should be a per-instance resource */
         g_pDbgFunctionHead = pNewDbgFuncNode;
     } else {
         free(pNewDbgFuncNode);
@@ -94,10 +96,27 @@
     return result;
 }
 
+static void* msg_callback_get_proc_addr(
+        const char      *funcName)
+{
+    if (!g_DEBUG_REPORT) {
+        return NULL;
+    }
+
+    if (!strcmp(funcName, "vkDbgCreateMsgCallback")) {
+        return (void *) vkDbgCreateMsgCallback;
+    }
+    if (!strcmp(funcName, "vkDbgDestroyMsgCallback")) {
+        return (void *) vkDbgDestroyMsgCallback;
+    }
+
+    return NULL;
+}
+
 // Utility function to handle reporting
 //  If callbacks are enabled, use them, otherwise use printf
 static void layerCbMsg(
-    VkFlags    msgFlags,
+    VkFlags             msgFlags,
     VkObjectType        objectType,
     VkObject            srcObject,
     size_t              location,
@@ -122,65 +141,4 @@
         }
         pTrav = pTrav->pNext;
     }
-#if 0
-    if (g_debugAction & (VK_DBG_LAYER_ACTION_LOG_MSG | VK_DBG_LAYER_ACTION_CALLBACK)) {
-        if (msgFlags & VK_DBG_REPORT_ERROR_BIT) {
-            if (g_reportFlags <= VK_DBG_LAYER_LEVEL_ERROR) {
-                if (g_debugAction & VK_DBG_LAYER_ACTION_LOG_MSG) {
-                    fprintf(g_logFile, "{%s}ERROR : %s\n", pLayerPrefix, pMsg);
-                    fflush(g_logFile);
-                }
-                if (g_debugAction & VK_DBG_LAYER_ACTION_CALLBACK) {
-                    while (pTrav) {
-                        pTrav->pfnMsgCallback(msgFlags,
-                                              objectType, srcObject,
-                                              location,
-                                              msgCode,
-                                              pLayerPrefix,
-                                              pMsg,
-                                              pTrav->pUserData);
-                        pTrav = pTrav->pNext;
-                    }
-                }
-            }
-        }
-        switch (msgType) {
-            case VK_DBG_REPORT_ERROR_BIT:
-                break;
-            case VK_DBG_MSG_WARNING:
-                if (g_reportFlags <= VK_DBG_LAYER_LEVEL_WARN) {
-                    if (g_debugAction & VK_DBG_LAYER_ACTION_LOG_MSG)
-                        fprintf(g_logFile, "{%s}WARN : %s\n", pLayerPrefix, pMsg);
-                    if (g_debugAction & VK_DBG_LAYER_ACTION_CALLBACK)
-                        while (pTrav) {
-				            pTrav->pfnMsgCallback(msgType, validationLevel, srcObject, location, msgCode, pMsg, pTrav->pUserData);
-                            pTrav = pTrav->pNext;
-                        }
-                }
-                break;
-            case VK_DBG_MSG_PERF_WARNING:
-                if (g_reportFlags <= VK_DBG_LAYER_LEVEL_PERF_WARN) {
-                    if (g_debugAction & VK_DBG_LAYER_ACTION_LOG_MSG)
-                        fprintf(g_logFile, "{%s}PERF_WARN : %s\n", pLayerPrefix, pMsg);
-                    if (g_debugAction & VK_DBG_LAYER_ACTION_CALLBACK)
-                        while (pTrav) {
-				            pTrav->pfnMsgCallback(msgType, validationLevel, srcObject, location, msgCode, pMsg, pTrav->pUserData);
-                            pTrav = pTrav->pNext;
-                        }
-                }
-                break;
-            default:
-                if (g_reportFlags <= VK_DBG_LAYER_LEVEL_INFO) {
-                    if (g_debugAction & VK_DBG_LAYER_ACTION_LOG_MSG)
-                        fprintf(g_logFile, "{%s}INFO : %s\n", pLayerPrefix, pMsg);
-                    if (g_debugAction & VK_DBG_LAYER_ACTION_CALLBACK)
-                        while (pTrav) {
-				            pTrav->pfnMsgCallback(msgType, validationLevel, srcObject, location, msgCode, pMsg, pTrav->pUserData);
-                            pTrav = pTrav->pNext;
-                        }
-                }
-                break;
-        }
-    }
-#endif
 }
diff --git a/layers/mem_tracker.cpp b/layers/mem_tracker.cpp
index 3898a54..85af9c2 100644
--- a/layers/mem_tracker.cpp
+++ b/layers/mem_tracker.cpp
@@ -863,6 +863,25 @@
     return res;
 }
 
+VkResult VKAPI vkCreateInstance(
+    const VkInstanceCreateInfo*                 pCreateInfo,
+    VkInstance*                                 pInstance)
+{
+    loader_platform_thread_once(&g_initOnce, initMemTracker);
+    /*
+     * For layers, the pInstance has already been filled out
+     * by the loader so that dispatch table is available.
+     */
+    initInstanceTable((const VkBaseLayerObject *) (*pInstance));
+
+    VkResult result = instance_dispatch_table(*pInstance)->CreateInstance(pCreateInfo, pInstance);
+
+    if (result == VK_SUCCESS) {
+        enable_debug_report(pCreateInfo->extensionCount, pCreateInfo->pEnabledExtensions);
+    }
+    return result;
+}
+
 VK_LAYER_EXPORT VkResult VKAPI vkCreateDevice(
     VkPhysicalDevice          gpu,
     const VkDeviceCreateInfo *pCreateInfo,
@@ -922,13 +941,19 @@
     uint32_t version;
     const char * const name;
 };
-#define MEM_TRACKER_LAYER_EXT_ARRAY_SIZE 1
+#define MEM_TRACKER_LAYER_EXT_ARRAY_SIZE 2
 static const VkExtensionProperties mtExts[MEM_TRACKER_LAYER_EXT_ARRAY_SIZE] = {
     {
         VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES,
         "MemTracker",
         0x10,
-        "Sample layer: MemTracker",
+        "Validation layer: MemTracker",
+    },
+    {
+        VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES,
+        "Validation",
+        0x10,
+        "Validation layer: MemTracker",
     }
 };
 
@@ -971,6 +996,45 @@
     return VK_SUCCESS;
 }
 
+VK_LAYER_EXPORT VkResult VKAPI vkGetPhysicalDeviceExtensionInfo(
+    VkPhysicalDevice     physical_device,
+    VkExtensionInfoType  infoType,
+    uint32_t             extensionIndex,
+    size_t              *pDataSize,
+    void                *pData)
+{
+    uint32_t *count;
+
+    if (pDataSize == NULL) {
+        return VK_ERROR_INVALID_POINTER;
+    }
+
+    switch (infoType) {
+        case VK_EXTENSION_INFO_TYPE_COUNT:
+            *pDataSize = sizeof(uint32_t);
+            if (pData == NULL) {
+                return VK_SUCCESS;
+            }
+            count = (uint32_t *) pData;
+            *count = MEM_TRACKER_LAYER_EXT_ARRAY_SIZE;
+            break;
+        case VK_EXTENSION_INFO_TYPE_PROPERTIES:
+            *pDataSize = sizeof(VkExtensionProperties);
+            if (pData == NULL) {
+                return VK_SUCCESS;
+            }
+            if (extensionIndex >= MEM_TRACKER_LAYER_EXT_ARRAY_SIZE) {
+                return VK_ERROR_INVALID_VALUE;
+            }
+            memcpy((VkExtensionProperties *) pData, &mtExts[extensionIndex], sizeof(VkExtensionProperties));
+            break;
+        default:
+            return VK_ERROR_INVALID_VALUE;
+    }
+
+    return VK_SUCCESS;
+}
+
 VK_LAYER_EXPORT VkResult VKAPI vkGetDeviceQueue(
     VkDevice  device,
     uint32_t  queueNodeIndex,
@@ -1252,6 +1316,10 @@
     uint32_t  fenceCount,
     VkFence  *pFences)
 {
+    /*
+     * TODO: Shouldn't we check for error conditions before passing down the chain?
+     * What if reason result is not VK_SUCCESS is something we could report as a validation error?
+     */
     VkResult result = device_dispatch_table(device)->ResetFences(device, fenceCount, pFences);
     if (VK_SUCCESS == result) {
         loader_platform_thread_lock_mutex(&globalLock);
@@ -2151,6 +2219,8 @@
     VkDevice         dev,
     const char       *funcName)
 {
+    void *fptr;
+
     if (dev == NULL) {
         return NULL;
     }
@@ -2296,7 +2366,11 @@
         return (void*) vkDestroySwapChainWSI;
     if (!strcmp(funcName, "vkGetSwapChainInfoWSI"))
         return (void*) vkGetSwapChainInfoWSI;
-    else
+
+    fptr = msg_callback_get_proc_addr(funcName);
+    if (fptr)
+        return fptr;
+
     {
         VkLayerDispatchTable **ppDisp = (VkLayerDispatchTable **) dev;
         VkLayerDispatchTable* pTable = tableMap[*ppDisp];
@@ -2310,6 +2384,7 @@
     VkInstance       instance,
     const char       *funcName)
 {
+    void *fptr;
     if (instance == NULL) {
         return NULL;
     }
@@ -2324,9 +2399,15 @@
 
     if (!strcmp(funcName, "vkDestroyInstance"))
         return (void *) vkDestroyInstance;
+    if (!strcmp(funcName, "vkCreateInstance"))
+        return (void*) vkCreateInstance;
     if (!strcmp(funcName, "vkCreateDevice"))
         return (void*) vkCreateDevice;
-    else
+
+    fptr = msg_callback_get_proc_addr(funcName);
+    if (fptr)
+        return fptr;
+
     {
         VkLayerInstanceDispatchTable **ppDisp = (VkLayerInstanceDispatchTable **) instance;
         VkLayerInstanceDispatchTable* pTable = tableInstanceMap[*ppDisp];
diff --git a/layers/param_checker.cpp b/layers/param_checker.cpp
index a27d54e..fa8f316 100644
--- a/layers/param_checker.cpp
+++ b/layers/param_checker.cpp
@@ -193,6 +193,10 @@
 
 VK_LAYER_EXPORT VkResult VKAPI vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo, VkInstance* pInstance)
 {
+    /* TODO: shouldn't we have initInstanceDispatch here? */
+    loader_platform_thread_once(&initOnce, initParamChecker);
+    initInstanceTable((const VkBaseLayerObject *) (*pInstance));
+
     PreCreateInstance(pCreateInfo->pAppInfo, pCreateInfo->pAllocCb);
     VkResult result = instance_dispatch_table(*pInstance)->CreateInstance(pCreateInfo, pInstance);
     PostCreateInstance(result, pCreateInfo, pInstance);
@@ -327,13 +331,19 @@
     return result;
 }
 
-#define PARAM_CHECKER_LAYER_EXT_ARRAY_SIZE 1
+#define PARAM_CHECKER_LAYER_EXT_ARRAY_SIZE 2
 static const VkExtensionProperties pcExts[PARAM_CHECKER_LAYER_EXT_ARRAY_SIZE] = {
     {
         VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES,
         "ParamChecker",
         0x10,
         "Sample layer: ParamChecker",
+    },
+    {
+        VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES,
+        "Validation",
+        0x10,
+        "Sample layer: ParamChecker",
     }
 };
 
@@ -379,8 +389,33 @@
                                                size_t*  pDataSize,
                                                void*    pData)
 {
-    VkResult result = instance_dispatch_table(gpu)->GetPhysicalDeviceExtensionInfo(gpu, infoType, extensionIndex, pDataSize, pData);
-    return result;
+    /* This entrypoint is NOT going to init it's own dispatch table since loader calls here early */
+    uint32_t *count;
+
+    if (pDataSize == NULL)
+        return VK_ERROR_INVALID_POINTER;
+
+    switch (infoType) {
+        case VK_EXTENSION_INFO_TYPE_COUNT:
+            *pDataSize = sizeof(uint32_t);
+            if (pData == NULL)
+                return VK_SUCCESS;
+            count = (uint32_t *) pData;
+            *count = PARAM_CHECKER_LAYER_EXT_ARRAY_SIZE;
+            break;
+        case VK_EXTENSION_INFO_TYPE_PROPERTIES:
+            *pDataSize = sizeof(VkExtensionProperties);
+            if (pData == NULL)
+                return VK_SUCCESS;
+            if (extensionIndex >= PARAM_CHECKER_LAYER_EXT_ARRAY_SIZE)
+                return VK_ERROR_INVALID_VALUE;
+            memcpy((VkExtensionProperties *) pData, &pcExts[extensionIndex], sizeof(VkExtensionProperties));
+            break;
+        default:
+            return VK_ERROR_INVALID_VALUE;
+    };
+
+    return VK_SUCCESS;
 }
 
 VK_LAYER_EXPORT VkResult VKAPI vkGetDeviceQueue(VkDevice device, uint32_t queueNodeIndex, uint32_t queueIndex, VkQueue* pQueue)
diff --git a/loader/loader.c b/loader/loader.c
index fd23465..b55ddcf 100644
--- a/loader/loader.c
+++ b/loader/loader.c
@@ -69,7 +69,7 @@
     .GetPhysicalDeviceInfo = loader_GetPhysicalDeviceInfo,
     .CreateDevice = loader_CreateDevice,
     .GetGlobalExtensionInfo = vkGetGlobalExtensionInfo,
-    .GetPhysicalDeviceExtensionInfo = loader_GetPhysicalDeviceExtensionInfo,
+    .GetPhysicalDeviceExtensionInfo = vkGetPhysicalDeviceExtensionInfo,
     .GetMultiDeviceCompatibility = loader_GetMultiDeviceCompatibility,
     .GetDisplayInfoWSI = loader_GetDisplayInfoWSI,
     .DbgCreateMsgCallback = loader_DbgCreateMsgCallback,
@@ -302,6 +302,52 @@
     return;
 }
 
+static void get_physical_device_layer_extensions(
+        struct loader_instance *ptr_instance,
+        VkPhysicalDevice physical_device,
+        const uint32_t layer_index,
+        struct loader_extension_list *ext_list)
+{
+    uint32_t i, count;
+    size_t siz = sizeof(count);
+    VkResult res;
+    loader_platform_dl_handle lib_handle;
+    PFN_vkGetPhysicalDeviceExtensionInfo fp_get;
+    struct loader_extension_property ext_props;
+
+    if (!loader.scanned_layers[layer_index].physical_device_extensions_supported) {
+        return;
+    }
+
+    ext_props.origin = VK_EXTENSION_ORIGIN_LAYER;
+    ext_props.lib_name = loader.scanned_layers[layer_index].lib_name;
+    char funcStr[256];
+    snprintf(funcStr, 256, "%sGetPhysicalDeviceExtensionInfo", ext_props.info.name);
+    lib_handle = loader_add_layer_lib("device", &ext_props);
+    fp_get = (PFN_vkGetPhysicalDeviceExtensionInfo) loader_platform_get_proc_address(lib_handle, "vkGetPhysicalDeviceExtensionInfo");
+    if (fp_get) {
+        res = fp_get(physical_device, VK_EXTENSION_INFO_TYPE_COUNT, 0, &siz, &count);
+        if (res == VK_SUCCESS) {
+            siz = sizeof(VkExtensionProperties);
+            for (i = 0; i < count; i++) {
+                memset(&ext_props, 0, sizeof(ext_props));
+                res = fp_get(physical_device, VK_EXTENSION_INFO_TYPE_PROPERTIES, i, &siz, &ext_props.info);
+                if (res == VK_SUCCESS && (ext_props.info.sType == VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES)) {
+                    ext_props.hosted = false;
+                    ext_props.origin = VK_EXTENSION_ORIGIN_LAYER;
+                    ext_props.lib_name = loader.scanned_layers[layer_index].lib_name;
+                    loader_add_to_ext_list(ext_list, 1, &ext_props);
+                }
+            }
+        } else {
+            loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Error getting physical device extension info count from Layer %s", ext_props.lib_name);
+        }
+    }
+
+    loader_remove_layer_lib(ptr_instance, &ext_props);
+    return;
+}
+
 static bool loader_init_ext_list(struct loader_extension_list *ext_info)
 {
     ext_info->capacity = 32 * sizeof(struct loader_extension_property);
@@ -490,6 +536,7 @@
     loader_platform_dl_handle handle;
     void *fp_create_inst;
     void *fp_get_global_ext_info;
+    void *fp_get_device_ext_info;
     struct loader_scanned_icds *new_node;
 
     // Used to call: dlopen(filename, RTLD_LAZY);
@@ -509,6 +556,7 @@
 
     LOOKUP(fp_create_inst, CreateInstance);
     LOOKUP(fp_get_global_ext_info, GetGlobalExtensionInfo);
+    LOOKUP(fp_get_device_ext_info, GetPhysicalDeviceExtensionInfo);
 #undef LOOKUP
 
     new_node = (struct loader_scanned_icds *) malloc(sizeof(struct loader_scanned_icds)
@@ -522,6 +570,7 @@
     new_node->CreateInstance = fp_create_inst;
     new_node->GetGlobalExtensionInfo = fp_get_global_ext_info;
     loader_init_ext_list(&new_node->global_extension_list);
+    loader_init_ext_list(&new_node->device_extension_list);
     new_node->next = loader.scanned_icd_list;
 
     new_node->lib_name = (char *) (new_node + 1);
@@ -794,6 +843,12 @@
                                  VK_EXTENSION_ORIGIN_LAYER,
                                  &loader.scanned_layers[count].global_extension_list);
 
+                     fp_get_ext = loader_platform_get_proc_address(handle,
+                                               "vkGetPhysicalDeviceExtensionInfo");
+                     if (fp_get_ext) {
+                         loader.scanned_layers[count].physical_device_extensions_supported = true;
+                     }
+
                      count++;
                      loader_platform_close_library(handle);
                  }
@@ -880,8 +935,8 @@
             /* Have already loaded this library, just increment ref count */
             loader.loaded_layer_lib_list[i].ref_count++;
             loader_log(VK_DBG_REPORT_INFO_BIT, 0,
-                       "Inserting %s layer %s from library %s", chain_type,
-                       ext_prop->info.name, ext_prop->lib_name);
+                       "%s Chain: Increment layer reference count for layer library %s",
+                       chain_type, ext_prop->lib_name);
             return loader.loaded_layer_lib_list[i].lib_handle;
         }
     }
@@ -896,7 +951,7 @@
 
     my_lib = &new_layer_lib_list[loader.loaded_layer_lib_count];
 
-    /* NOTE: We require that the extension property to be immutable */
+    /* NOTE: We require that the extension property be immutable */
     my_lib->lib_name = ext_prop->lib_name;
     my_lib->ref_count = 0;
     my_lib->lib_handle = NULL;
@@ -907,8 +962,8 @@
         return NULL;
     } else {
         loader_log(VK_DBG_REPORT_INFO_BIT, 0,
-                   "Inserting %s layer %s from library %s", chain_type,
-                   ext_prop->info.name, ext_prop->lib_name);
+                   "Chain: %s: Loading layer library %s",
+                   chain_type, ext_prop->lib_name);
     }
     loader.loaded_layer_lib_count++;
     loader.loaded_layer_lib_list = new_layer_lib_list;
@@ -941,9 +996,15 @@
     my_lib->ref_count--;
     inst->layer_count--;
     if (my_lib->ref_count > 0) {
+        loader_log(VK_DBG_REPORT_INFO_BIT, 0,
+                   "Decrement reference count for layer library %s", ext_prop->lib_name);
         return;
     }
 
+    loader_platform_close_library(my_lib->lib_handle);
+    loader_log(VK_DBG_REPORT_INFO_BIT, 0,
+               "Unloading layer library %s", ext_prop->lib_name);
+
     /* Need to remove unused library from list */
     new_layer_lib_list = malloc((loader.loaded_layer_lib_count - 1) * sizeof(struct loader_lib_info));
     if (!new_layer_lib_list) {
@@ -961,6 +1022,7 @@
         memcpy(&new_layer_lib_list[idx], &loader.loaded_layer_lib_list[idx+1],
                 sizeof(struct loader_lib_info) * (loader.loaded_layer_lib_count - idx - 1));
     }
+
     free(loader.loaded_layer_lib_list);
     loader.loaded_layer_lib_count--;
     loader.loaded_layer_lib_list = new_layer_lib_list;
@@ -1133,6 +1195,10 @@
             continue;
         }
 
+        loader_log(VK_DBG_REPORT_INFO_BIT, 0,
+                   "Insert instance layer library %s for extension: %s",
+                   ext_prop->lib_name, ext_prop->info.name);
+
         layer_idx--;
     }
 
@@ -1141,6 +1207,14 @@
     return inst->layer_count;
 }
 
+void loader_activate_instance_layer_extensions(struct loader_instance *inst)
+{
+
+    loader_init_instance_extension_dispatch_table(inst->disp,
+                                                  inst->disp->GetInstanceProcAddr,
+                                                  (VkInstance) inst->wrappedInstance);
+}
+
 void loader_enable_device_layers(struct loader_icd *icd, uint32_t gpu_index)
 {
     if (icd == NULL)
@@ -1220,6 +1294,10 @@
                 continue;
             }
 
+            loader_log(VK_DBG_REPORT_INFO_BIT, 0,
+                       "Insert device layer library %s for extension: %s",
+                       ext_prop->lib_name, ext_prop->info.name);
+
             layer_idx--;
         }
 
@@ -1315,79 +1393,142 @@
     return VK_SUCCESS;
 }
 
+VkResult loader_init_physical_device_info(
+        struct loader_instance *ptr_instance)
+{
+    struct loader_icd *icd;
+    uint32_t n, count = 0;
+    VkResult res = VK_ERROR_UNKNOWN;
+
+    icd = ptr_instance->icds;
+    while (icd) {
+        res = icd->EnumeratePhysicalDevices(icd->instance, &n, NULL);
+        if (res != VK_SUCCESS)
+            return res;
+        icd->gpu_count = n;
+        count += n;
+        icd = icd->next;
+    }
+
+    ptr_instance->total_gpu_count = count;
+
+    VkPhysicalDevice* gpus;
+    gpus = malloc( sizeof(VkPhysicalDevice) *  count);
+    if (!gpus) {
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+    }
+
+    icd = ptr_instance->icds;
+    while (icd) {
+        VkBaseLayerObject * wrapped_gpus;
+        PFN_vkGetDeviceProcAddr get_proc_addr = icd->GetDeviceProcAddr;
+
+        n = icd->gpu_count;
+        res = icd->EnumeratePhysicalDevices(
+                                        icd->instance,
+                                        &n,
+                                        gpus);
+        if (res == VK_SUCCESS && n) {
+            wrapped_gpus = (VkBaseLayerObject*) malloc(n *
+                                        sizeof(VkBaseLayerObject));
+            if (!wrapped_gpus) {
+                /* TODO: Add cleanup code here */
+                return VK_ERROR_OUT_OF_HOST_MEMORY;
+            }
+
+            icd->gpus = wrapped_gpus;
+            icd->loader_dispatch = (VkLayerDispatchTable *) malloc(n *
+                                    sizeof(VkLayerDispatchTable));
+            for (unsigned int i = 0; i < n; i++) {
+                (wrapped_gpus + i)->baseObject = gpus[i];
+                (wrapped_gpus + i)->pGPA = get_proc_addr;
+                (wrapped_gpus + i)->nextObject = gpus[i];
+
+                loader_init_device_dispatch_table(icd->loader_dispatch + i,
+                                           get_proc_addr, gpus[i], gpus[i]);
+
+                loader_init_dispatch(gpus[i], ptr_instance->disp);
+
+                if (!loader_init_ext_list(&icd->device_extension_cache[i])) {
+                    /* TODO: Add cleanup code here */
+                    res = VK_ERROR_OUT_OF_HOST_MEMORY;
+                }
+                if (res == VK_SUCCESS && icd->GetPhysicalDeviceExtensionInfo) {
+                    size_t data_size;
+                    uint32_t extension_count;
+
+                    data_size = sizeof(extension_count);
+                    res = icd->GetPhysicalDeviceExtensionInfo(gpus[i], VK_EXTENSION_INFO_TYPE_COUNT, 0, &data_size, &extension_count);
+                    if (data_size == sizeof(extension_count) && res == VK_SUCCESS) {
+                        struct loader_extension_property ext_props;
+
+                        /* Gather all the ICD extensions */
+                        for (uint32_t extension_id = 0; extension_id < extension_count; extension_id++) {
+                            data_size = sizeof(VkExtensionProperties);
+                            res = icd->GetPhysicalDeviceExtensionInfo(gpus[i], VK_EXTENSION_INFO_TYPE_PROPERTIES,
+                                                                      extension_id, &data_size, &ext_props.info);
+                            if (data_size == sizeof(VkExtensionProperties) && res == VK_SUCCESS) {
+                                ext_props.hosted = false;
+                                ext_props.origin = VK_EXTENSION_ORIGIN_ICD;
+                                ext_props.lib_name = icd->scanned_icds->lib_name;
+                                loader_add_to_ext_list(&icd->device_extension_cache[i], 1, &ext_props);
+                            }
+                        }
+
+                        // Traverse layers list adding non-duplicate extensions to the list
+                        for (uint32_t l = 0; l < loader.scanned_layer_count; l++) {
+                            get_physical_device_layer_extensions(ptr_instance, gpus[i], l, &icd->device_extension_cache[i]);
+                        }
+                    }
+                }
+
+                if (res != VK_SUCCESS) {
+                    /* clean up any extension lists previously created before this request failed */
+                    for (uint32_t j = 0; j < i; j++) {
+                        loader_destroy_ext_list(&icd->device_extension_cache[i]);
+                    }
+                    return res;
+                }
+            }
+
+            count += n;
+        }
+
+        icd = icd->next;
+    }
+
+    return VK_SUCCESS;
+}
+
 VkResult loader_EnumeratePhysicalDevices(
         VkInstance                              instance,
         uint32_t*                               pPhysicalDeviceCount,
         VkPhysicalDevice*                       pPhysicalDevices)
 {
+    uint32_t index = 0;
     struct loader_instance *ptr_instance = (struct loader_instance *) instance;
-    struct loader_icd *icd;
-    uint32_t n, count = 0;
-    VkResult res = VK_ERROR_UNKNOWN;
+    struct loader_icd *icd = ptr_instance->icds;
 
-    //in spirit of VK don't error check on the instance parameter
-    icd = ptr_instance->icds;
-    if (pPhysicalDevices == NULL) {
-        while (icd) {
-            res = icd->EnumeratePhysicalDevices(icd->instance, &n, NULL);
-            if (res != VK_SUCCESS)
-                return res;
-            icd->gpu_count = n;
-            count += n;
-            icd = icd->next;
-        }
-
-        ptr_instance->total_gpu_count = count;
-
-    } else
-    {
-        VkPhysicalDevice* gpus;
-        if (*pPhysicalDeviceCount < ptr_instance->total_gpu_count)
-            return VK_ERROR_INVALID_VALUE;
-        gpus = malloc( sizeof(VkPhysicalDevice) *  *pPhysicalDeviceCount);
-        if (!gpus)
-            return VK_ERROR_OUT_OF_HOST_MEMORY;
-        while (icd) {
-            VkBaseLayerObject * wrapped_gpus;
-            PFN_vkGetDeviceProcAddr get_proc_addr = icd->GetDeviceProcAddr;
-
-            n = *pPhysicalDeviceCount;
-            res = icd->EnumeratePhysicalDevices(
-                                            icd->instance,
-                                            &n,
-                                            gpus);
-            if (res == VK_SUCCESS && n) {
-                wrapped_gpus = (VkBaseLayerObject*) malloc(n *
-                                            sizeof(VkBaseLayerObject));
-                icd->gpus = wrapped_gpus;
-                icd->gpu_count = n;
-                icd->loader_dispatch = (VkLayerDispatchTable *) malloc(n *
-                                        sizeof(VkLayerDispatchTable));
-                for (unsigned int i = 0; i < n; i++) {
-                    (wrapped_gpus + i)->baseObject = gpus[i];
-                    (wrapped_gpus + i)->pGPA = get_proc_addr;
-                    (wrapped_gpus + i)->nextObject = gpus[i];
-                    memcpy(pPhysicalDevices + count, gpus, sizeof(*pPhysicalDevices));
-                    loader_init_device_dispatch_table(icd->loader_dispatch + i,
-                                               get_proc_addr, gpus[i], gpus[i]);
-
-                    loader_init_dispatch(gpus[i], ptr_instance->disp);
-                }
-
-                count += n;
-
-                if (count >= *pPhysicalDeviceCount) {
-                    break;
-                }
-            }
-
-            icd = icd->next;
-        }
+    /* TODO: How do we only do this once? */
+    if (ptr_instance->total_gpu_count == 0) {
+        loader_init_physical_device_info(ptr_instance);
     }
 
-    *pPhysicalDeviceCount = count;
+    *pPhysicalDeviceCount = ptr_instance->total_gpu_count;
+    if (!pPhysicalDevices) {
+        return VK_SUCCESS;
+    }
 
-    return (count > 0) ? VK_SUCCESS : res;
+    while (icd) {
+        assert((index + icd->gpu_count) <= *pPhysicalDeviceCount);
+        for (uint32_t i = 0; i < icd->gpu_count; i++) {
+            memcpy(&pPhysicalDevices[index], &icd->gpus[i].baseObject, sizeof(VkPhysicalDevice));
+        }
+        index += icd->gpu_count;
+        icd = icd->next;
+    }
+
+    return VK_SUCCESS;
 }
 
 VkResult loader_GetPhysicalDeviceInfo(
@@ -1572,7 +1713,8 @@
 
     return VK_SUCCESS;
 }
-VkResult loader_GetPhysicalDeviceExtensionInfo(
+
+LOADER_EXPORT VkResult VKAPI vkGetPhysicalDeviceExtensionInfo(
         VkPhysicalDevice                        gpu,
         VkExtensionInfoType                     infoType,
         uint32_t                                extensionIndex,
@@ -1580,14 +1722,35 @@
         void*                                   pData)
 {
     uint32_t gpu_index;
+    uint32_t *count;
     struct loader_icd *icd = loader_get_icd((const VkBaseLayerObject *) gpu, &gpu_index);
-    VkResult res = VK_ERROR_INITIALIZATION_FAILED;
 
-    if (icd->GetPhysicalDeviceExtensionInfo)
-        res = icd->GetPhysicalDeviceExtensionInfo(gpu, infoType, extensionIndex,
-                                                  pDataSize, pData);
+    if (pDataSize == NULL)
+        return VK_ERROR_INVALID_POINTER;
 
-    return res;
+    switch (infoType) {
+        case VK_EXTENSION_INFO_TYPE_COUNT:
+            *pDataSize = sizeof(uint32_t);
+            if (pData == NULL)
+                return VK_SUCCESS;
+            count = (uint32_t *) pData;
+            *count = icd->device_extension_cache[gpu_index].count;
+            break;
+        case VK_EXTENSION_INFO_TYPE_PROPERTIES:
+            *pDataSize = sizeof(VkExtensionProperties);
+            if (pData == NULL)
+                return VK_SUCCESS;
+            if (extensionIndex >= icd->device_extension_cache[gpu_index].count)
+                return VK_ERROR_INVALID_VALUE;
+            memcpy((VkExtensionProperties *) pData,
+                   &icd->device_extension_cache[gpu_index].list[extensionIndex],
+                   sizeof(VkExtensionProperties));
+            break;
+        default:
+            return VK_ERROR_INVALID_VALUE;
+    };
+
+    return VK_SUCCESS;
 }
 
 VkResult loader_GetMultiDeviceCompatibility(
diff --git a/loader/loader.h b/loader/loader.h
index 8b427b5..2d3b067 100644
--- a/loader/loader.h
+++ b/loader/loader.h
@@ -69,16 +69,14 @@
     char *lib_name;
 
     /* cache of global extensions for a specific layer */
-//    uint32_t global_extension_count;
-//    struct loader_extension_property *global_extensions;
     struct loader_extension_list global_extension_list;
 
+    bool physical_device_extensions_supported;
     /*
      * cache of device extensions for a specific layer,
      * filled in at CreateInstance time
      */
-    uint32_t device_ext_count;
-    struct loader_extension_property *device_ext_list;
+    struct loader_extension_list physical_device_extension_list;
 };
 
 struct loader_icd {
@@ -105,6 +103,13 @@
     uint32_t  app_extension_count[MAX_GPUS_FOR_LAYER];
     VkExtensionProperties *app_extension_props[MAX_GPUS_FOR_LAYER];
 
+    /*
+     * Fill in the cache of available extensions from all layers that
+     * operate with this physical device.
+     * This cache will be used to satisfy calls to GetPhysicalDeviceExtensionInfo
+     */
+    struct loader_extension_list device_extension_cache[MAX_GPUS_FOR_LAYER];
+
     struct loader_extension_list enabled_device_extensions[MAX_GPUS_FOR_LAYER];
 };
 
@@ -238,8 +243,7 @@
      * cache of device extensions for specific ICD,
      * filled in at CreateInstance time
      */
-    uint32_t device_extension_count;
-    struct loader_extension_property *device_extensions;
+    struct loader_extension_list device_extension_list;
 };
 
 static inline void loader_set_dispatch(VkObject obj, const void *data)
@@ -312,7 +316,6 @@
         uint32_t                                extensionIndex,
         size_t*                                 pDataSize,
         void*                                   pData);
-#endif
 
 VkResult loader_GetPhysicalDeviceExtensionInfo(
         VkPhysicalDevice                        gpu,
@@ -320,6 +323,7 @@
         uint32_t                                extensionIndex,
         size_t*                                 pDataSize,
         void*                                   pData);
+#endif
 
 VkResult loader_GetMultiDeviceCompatibility(
         VkPhysicalDevice                        gpu0,
@@ -343,7 +347,15 @@
 void layer_lib_scan(void);
 void loader_coalesce_extensions(void);
 
+static loader_platform_dl_handle loader_add_layer_lib(
+        const char *chain_type,
+        struct loader_extension_property *ext_prop);
+static void loader_remove_layer_lib(
+        struct loader_instance *inst,
+        struct loader_extension_property *ext_prop);
+
 struct loader_icd * loader_get_icd(const VkBaseLayerObject *gpu,
                                    uint32_t *gpu_index);
 uint32_t loader_activate_instance_layers(struct loader_instance *inst);
+void loader_activate_instance_layer_extensions(struct loader_instance *inst);
 #endif /* LOADER_H */
diff --git a/loader/table_ops.h b/loader/table_ops.h
index 93131b1..e4c39f2 100644
--- a/loader/table_ops.h
+++ b/loader/table_ops.h
@@ -387,7 +387,13 @@
     table->GetPhysicalDeviceExtensionInfo = (PFN_vkGetPhysicalDeviceExtensionInfo) gpa(inst, "vkGetPhysicalDeviceExtensionInfo");
     table->GetMultiDeviceCompatibility = (PFN_vkGetMultiDeviceCompatibility) gpa(inst, "vkGetMultiDeviceCompatibility");
     table->GetDisplayInfoWSI = (PFN_vkGetDisplayInfoWSI) gpa(inst, "vkGetDisplayInfoWSI");
+}
 
+static inline void loader_init_instance_extension_dispatch_table(
+        VkLayerInstanceDispatchTable *table,
+        PFN_vkGetInstanceProcAddr gpa,
+        VkInstance inst)
+{
     table->DbgCreateMsgCallback = (PFN_vkDbgCreateMsgCallback) gpa(inst, "vkDbgCreateMsgCallback");
     table->DbgDestroyMsgCallback = (PFN_vkDbgDestroyMsgCallback) gpa(inst, "vkDbgDestroyMsgCallback");
 }
diff --git a/loader/trampoline.c b/loader/trampoline.c
index 8503971..d22df04 100644
--- a/loader/trampoline.c
+++ b/loader/trampoline.c
@@ -120,6 +120,14 @@
 
     res = ptr_instance->disp->CreateInstance(pCreateInfo, pInstance);
 
+    /*
+     * Finally have the layers in place and everyone has seen
+     * the CreateInstance command go by. This allows the layer's
+     * GetInstanceProcAddr functions to return valid extension functions
+     * if enabled.
+     */
+    loader_activate_instance_layer_extensions(ptr_instance);
+
     return res;
 }
 
@@ -199,31 +207,6 @@
     return res;
 }
 
-#if 0 //TODO get working on layer instance chain
-LOADER_EXPORT VkResult VKAPI vkGetGlobalExtensionInfo(
-                                               VkExtensionInfoType infoType,
-                                               uint32_t extensionIndex,
-                                               size_t*  pDataSize,
-                                               void*    pData)
-{
-    return instance_disp.GetGlobalExtensionInfo(infoType, extensionIndex, pDataSize, pData);
-}
-#endif
-
-LOADER_EXPORT VkResult VKAPI vkGetPhysicalDeviceExtensionInfo(
-                                                VkPhysicalDevice gpu,
-                                                VkExtensionInfoType infoType,
-                                                uint32_t extensionIndex,
-                                                size_t* pDataSize,
-                                                void* pData)
-{
-    const VkLayerInstanceDispatchTable *disp;
-
-    disp = loader_get_instance_dispatch(gpu);
-
-    return disp->GetPhysicalDeviceExtensionInfo(gpu, infoType, extensionIndex, pDataSize, pData);
-}
-
 LOADER_EXPORT VkResult VKAPI vkGetDeviceQueue(VkDevice device, uint32_t queueNodeIndex, uint32_t queueIndex, VkQueue* pQueue)
 {
     const VkLayerDispatchTable *disp;
diff --git a/tests/layer_validation_tests.cpp b/tests/layer_validation_tests.cpp
index 5c69e3c..e9cf958 100644
--- a/tests/layer_validation_tests.cpp
+++ b/tests/layer_validation_tests.cpp
@@ -152,6 +152,13 @@
         std::vector<const char *> device_extension_names;
 
         instance_extension_names.push_back(DEBUG_REPORT_EXTENSION_NAME);
+        instance_extension_names.push_back("MemTracker");
+        instance_extension_names.push_back("ObjectTracker");
+        instance_extension_names.push_back("Threading");
+
+        device_extension_names.push_back("MemTracker");
+        device_extension_names.push_back("ObjectTracker");
+        device_extension_names.push_back("Threading");
 
         // Force layer output level to be >= WARNING so that we catch those messages but ignore others
         setLayerOptionEnum("MemTrackerReportLevel",    "VK_DBG_LAYER_LEVEL_WARNING");
@@ -806,34 +813,6 @@
 }
 #endif
 #if OBJECT_TRACKER_TESTS
-TEST_F(VkLayerTest, WaitForUnsubmittedFence)
-{
-    vk_testing::Fence testFence;
-    VkFlags msgFlags;
-    std::string msgString;
-    VkFenceCreateInfo fenceInfo = {};
-    fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
-    fenceInfo.pNext = NULL;
-
-    ASSERT_NO_FATAL_FAILURE(InitState());
-    testFence.init(*m_device, fenceInfo);
-    m_errorMonitor->ClearState();
-    vkGetFenceStatus(m_device->device(),testFence.obj());
-    msgFlags = m_errorMonitor->GetState(&msgString);
-    ASSERT_TRUE(msgFlags & VK_DBG_REPORT_ERROR_BIT) << "Did not receive an error asking for status of unsubmitted fence";
-    if (!strstr(msgString.c_str(),"Status Requested for Unsubmitted Fence")) {
-        FAIL() << "Error received was not Status Requested for Unsubmitted Fence";
-    }
-
-    VkFence fences[1] = {testFence.obj()};
-    m_errorMonitor->ClearState();
-    vkWaitForFences(m_device->device(), 1, fences, VK_TRUE, 0);
-    msgFlags = m_errorMonitor->GetState(&msgString);
-    ASSERT_TRUE(msgFlags & VK_DBG_REPORT_ERROR_BIT) << "Did not receive an error for waiting for unsubmitted fence";
-    if (!strstr(msgString.c_str(),"Waiting for Unsubmitted Fence")) {
-        FAIL() << "Error received was not 'Waiting for Unsubmitted Fence'";
-    }
-}
 
 TEST_F(VkLayerTest, GetObjectInfoMismatchedType)
 {
diff --git a/tests/vkrenderframework.cpp b/tests/vkrenderframework.cpp
index a658bbe..f206d06 100644
--- a/tests/vkrenderframework.cpp
+++ b/tests/vkrenderframework.cpp
@@ -120,7 +120,7 @@
                                          VK_DBG_REPORT_ERROR_BIT | VK_DBG_REPORT_WARN_BIT,
                                          dbgFunction,
                                          userData,
-                                         &m_msgCallback);
+                                         &m_globalMsgCallback);
             ASSERT_VK_SUCCESS(err);
         }
     }
@@ -149,6 +149,18 @@
 //    ASSERT_NE(obj_name, (PFN_vkDbgCreateMsgCallback) NULL) << "Did not get function pointer for DbgCreateMsgCallback";
 //    obj_name()
     m_device = new VkDeviceObj(0, objs[0], device_extensions);
+
+    /* Now register callback on device */
+    if (0) {
+        if (m_dbgCreateMsgCallback) {
+            err = m_dbgCreateMsgCallback(this->inst,
+                                         VK_DBG_REPORT_ERROR_BIT | VK_DBG_REPORT_WARN_BIT,
+                                         dbgFunction,
+                                         userData,
+                                         &m_devMsgCallback);
+            ASSERT_VK_SUCCESS(err);
+        }
+    }
     m_device->get_device_queue();
 
     m_depthStencil = new VkDepthStencilObj();
diff --git a/tests/vkrenderframework.h b/tests/vkrenderframework.h
index 024bdba..e761001 100644
--- a/tests/vkrenderframework.h
+++ b/tests/vkrenderframework.h
@@ -129,7 +129,8 @@
     VkDepthStencilObj                  *m_depthStencil;
     VkMemoryRefManager                  m_mem_ref_mgr;
     PFN_vkDbgCreateMsgCallback          m_dbgCreateMsgCallback;
-    VkDbgMsgCallback                    m_msgCallback;
+    VkDbgMsgCallback                    m_globalMsgCallback;
+    VkDbgMsgCallback                    m_devMsgCallback;
 
     /*
      * SetUp and TearDown are called by the Google Test framework
diff --git a/vk-layer-generate.py b/vk-layer-generate.py
index c1d6fdc..d3488f6 100755
--- a/vk-layer-generate.py
+++ b/vk-layer-generate.py
@@ -33,7 +33,7 @@
 import vk_helper
 
 def proto_is_global(proto):
-    if proto.params[0].ty == "VkInstance" or proto.params[0].ty == "VkPhysicalDevice" or proto.name == "CreateInstance" or proto.name == "GetGlobalExtensionInfo" or proto.name == "GetDisplayInfoWSI":
+    if proto.params[0].ty == "VkInstance" or proto.params[0].ty == "VkPhysicalDevice" or proto.name == "CreateInstance" or proto.name == "GetGlobalExtensionInfo" or proto.name == "GetPhysicalDeviceExtensionInfo" or proto.name == "GetDisplayInfoWSI":
        return True
     else:
        return False
@@ -175,15 +175,32 @@
 
     def _gen_layer_get_global_extension_info(self, layer="Generic"):
         ggei_body = []
-        ggei_body.append('#define LAYER_EXT_ARRAY_SIZE 1')
-        ggei_body.append('static const VkExtensionProperties layerExts[LAYER_EXT_ARRAY_SIZE] = {')
-        ggei_body.append('    {')
-        ggei_body.append('        VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES,')
-        ggei_body.append('        "%s",' % layer)
-        ggei_body.append('        0x10,')
-        ggei_body.append('        "layer: %s",' % layer)
-        ggei_body.append('    }')
-        ggei_body.append('};')
+        if layer == 'APIDump':
+            ggei_body.append('#define LAYER_EXT_ARRAY_SIZE 1')
+            ggei_body.append('static const VkExtensionProperties layerExts[LAYER_EXT_ARRAY_SIZE] = {')
+            ggei_body.append('    {')
+            ggei_body.append('        VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES,')
+            ggei_body.append('        "%s",' % layer)
+            ggei_body.append('        0x10,')
+            ggei_body.append('        "layer: %s",' % layer)
+            ggei_body.append('    }')
+            ggei_body.append('};')
+        else:
+            ggei_body.append('#define LAYER_EXT_ARRAY_SIZE 2')
+            ggei_body.append('static const VkExtensionProperties layerExts[LAYER_EXT_ARRAY_SIZE] = {')
+            ggei_body.append('    {')
+            ggei_body.append('        VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES,')
+            ggei_body.append('        "%s",' % layer)
+            ggei_body.append('        0x10,')
+            ggei_body.append('        "layer: %s",' % layer)
+            ggei_body.append('    },')
+            ggei_body.append('    {')
+            ggei_body.append('        VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES,')
+            ggei_body.append('        "Validation",')
+            ggei_body.append('        0x10,')
+            ggei_body.append('        "layer: %s",' % layer)
+            ggei_body.append('    }')
+            ggei_body.append('};')
         ggei_body.append('')
         ggei_body.append('VK_LAYER_EXPORT VkResult VKAPI vkGetGlobalExtensionInfo(VkExtensionInfoType infoType, uint32_t extensionIndex, size_t* pDataSize, void* pData)')
         ggei_body.append('{')
@@ -215,6 +232,39 @@
         ggei_body.append('}')
         return "\n".join(ggei_body)
 
+    def _gen_layer_get_physical_device_extension_info(self, layer="Generic"):
+        ggei_body = []
+        ggei_body.append('')
+        ggei_body.append('VK_LAYER_EXPORT VkResult VKAPI vkGetPhysicalDeviceExtensionInfo(VkPhysicalDevice physicalDevice, VkExtensionInfoType infoType, uint32_t extensionIndex, size_t* pDataSize, void* pData)')
+        ggei_body.append('{')
+        ggei_body.append('    uint32_t *count;')
+        ggei_body.append('')
+        ggei_body.append('    if (pDataSize == NULL)')
+        ggei_body.append('        return VK_ERROR_INVALID_POINTER;')
+        ggei_body.append('')
+        ggei_body.append('    switch (infoType) {')
+        ggei_body.append('        case VK_EXTENSION_INFO_TYPE_COUNT:')
+        ggei_body.append('            *pDataSize = sizeof(uint32_t);')
+        ggei_body.append('            if (pData == NULL)')
+        ggei_body.append('                return VK_SUCCESS;')
+        ggei_body.append('            count = (uint32_t *) pData;')
+        ggei_body.append('            *count = LAYER_EXT_ARRAY_SIZE;')
+        ggei_body.append('            break;')
+        ggei_body.append('        case VK_EXTENSION_INFO_TYPE_PROPERTIES:')
+        ggei_body.append('            *pDataSize = sizeof(VkExtensionProperties);')
+        ggei_body.append('            if (pData == NULL)')
+        ggei_body.append('                return VK_SUCCESS;')
+        ggei_body.append('            if (extensionIndex >= LAYER_EXT_ARRAY_SIZE)')
+        ggei_body.append('                return VK_ERROR_INVALID_VALUE;')
+        ggei_body.append('            memcpy((VkExtensionProperties *) pData, &layerExts[extensionIndex], sizeof(VkExtensionProperties));')
+        ggei_body.append('            break;')
+        ggei_body.append('        default:')
+        ggei_body.append('            return VK_ERROR_INVALID_VALUE;')
+        ggei_body.append('    };')
+        ggei_body.append('    return VK_SUCCESS;')
+        ggei_body.append('}')
+        return "\n".join(ggei_body)
+
     def _generate_dispatch_entrypoints(self, qual=""):
         if qual:
             qual += " "
@@ -236,6 +286,8 @@
                         funcs.append('/* CreateDevice HERE */')
                     elif 'GetGlobalExtensionInfo' == proto.name:
                         intercept = self._gen_layer_get_global_extension_info(self.layer_name)
+                    elif 'GetPhysicalDeviceExtensionInfo' == proto.name:
+                        intercept = self._gen_layer_get_physical_device_extension_info(self.layer_name)
                 if intercept is not None:
                     funcs.append(intercept)
                     intercepted.append(proto)
@@ -538,7 +590,7 @@
         gen_header.append('}')
         return "\n".join(gen_header)
     def generate_intercept(self, proto, qual):
-        if proto.name in [ 'GetGlobalExtensionInfo' ]:
+        if proto.name in [ 'GetGlobalExtensionInfo', 'GetPhysicalDeviceExtensionInfo' ]:
             # use default version
             return None
         decl = proto.c_func(prefix="vk", attr="VKAPI")
@@ -812,7 +864,7 @@
         return "\n".join(func_body)
 
     def generate_intercept(self, proto, qual):
-        if proto.name in [ 'GetGlobalExtensionInfo']:
+        if proto.name in [ 'GetGlobalExtensionInfo', 'GetPhysicalDeviceExtensionInfo']:
             return None
         decl = proto.c_func(prefix="vk", attr="VKAPI")
         ret_val = ''
@@ -1250,7 +1302,7 @@
         return "\n".join(header_txt)
 
     def generate_intercept(self, proto, qual):
-        if proto.name in [ 'DbgCreateMsgCallback', 'GetGlobalExtensionInfo' ]:
+        if proto.name in [ 'DbgCreateMsgCallback', 'GetGlobalExtensionInfo', 'GetPhysicalDeviceExtensionInfo' ]:
             # use default version
             return None