vulkan.h: Remove vkGetFormatInfo, add features/limits (#12827, v125)

NOTES:

1/ Some layers impact from vkGetFormatInfo ->
vkGetPhysicalDeviceFormatInfo; some checks are currently disabled in
ParamChecker pending discussion on the best way to do this. Similar
checks in Image layer implemented via additional layer_data member
to link back from VkDevice -> VkPhysicalDevice.

2/ VkPhysicalDeviceFeatures, VkPhysicalDeviceLimits members all zero
for now; also some further churn to be done to the contents of these
structures.

Signed-off-by: Chris Forbes <chrisf@ijw.co.nz>
diff --git a/include/vkLayer.h b/include/vkLayer.h
index 865bb64..43e4478 100644
--- a/include/vkLayer.h
+++ b/include/vkLayer.h
@@ -58,7 +58,6 @@
     PFN_vkResetEvent ResetEvent;
     PFN_vkCreateQueryPool CreateQueryPool;
     PFN_vkGetQueryPoolResults GetQueryPoolResults;
-    PFN_vkGetFormatInfo GetFormatInfo;
     PFN_vkCreateBuffer CreateBuffer;
     PFN_vkCreateBufferView CreateBufferView;
     PFN_vkCreateImage CreateImage;
@@ -143,6 +142,9 @@
     PFN_vkDestroyInstance DestroyInstance;
     PFN_vkEnumeratePhysicalDevices EnumeratePhysicalDevices;
     PFN_vkGetPhysicalDeviceInfo GetPhysicalDeviceInfo;
+    PFN_vkGetPhysicalDeviceFeatures GetPhysicalDeviceFeatures;
+    PFN_vkGetPhysicalDeviceFormatInfo GetPhysicalDeviceFormatInfo;
+    PFN_vkGetPhysicalDeviceLimits GetPhysicalDeviceLimits;
     PFN_vkCreateDevice CreateDevice;
     /* PFN_vkGetGlobalExtensionInfo GetGlobalExtensionInfo; non-dispatchable */
     PFN_vkGetPhysicalDeviceExtensionInfo GetPhysicalDeviceExtensionInfo;
diff --git a/include/vulkan.h b/include/vulkan.h
index bb40adf..131d36f 100644
--- a/include/vulkan.h
+++ b/include/vulkan.h
@@ -554,14 +554,6 @@
     VK_ENUM_RANGE(EXTENSION_INFO_TYPE, COUNT, PROPERTIES)
 } VkExtensionInfoType;
 
-typedef enum VkFormatInfoType_
-{
-    // Info type for vkGetFormatInfo()
-    VK_FORMAT_INFO_TYPE_PROPERTIES                          = 0x00000000,
-
-    VK_ENUM_RANGE(FORMAT_INFO_TYPE, PROPERTIES, PROPERTIES)
-} VkFormatInfoType;
-
 typedef enum VkSubresourceInfoType_
 {
     // Info type for vkGetImageSubresourceInfo()
@@ -1223,6 +1215,49 @@
     uint32_t                                    maxColorAttachments;            // at least 8?
 } VkPhysicalDeviceProperties;
 
+typedef struct VkPhysicalDeviceFeatures_
+{
+    // GFL_32 features
+    bool32_t                                    supportsGeometryShader;
+    bool32_t                                    supportsTessellationShader;
+    bool32_t                                    supportsSampleRateShading;
+    bool32_t                                    supportsFragmentSideEffects;
+    bool32_t                                    supportsConstantStorageBufferArrayIdexing;
+    bool32_t                                    supportsConstantStorageImageArrayIndexing;
+    bool32_t                                    supportsConstantUniformBufferArrayIndexing;
+    bool32_t                                    supportsDynamicSampledImageArrayIndexing;
+    // GFL_45 features
+    bool32_t                                    supportsBlendSrc1;
+    bool32_t                                    supportsClipAndCullDistance;
+    bool32_t                                    supportsLogicOp;
+    bool32_t                                    supportsInstancedDrawIndirect;
+    bool32_t                                    supportsDepthClip;
+    bool32_t                                    supportsFillMode;
+    bool32_t                                    supportsStorageImageExtendedFormats;
+    bool32_t                                    supportsStorageImageMultisample;
+    bool32_t                                    supportsPipelineStatisticsQuery;
+    bool32_t                                    supportsVTGSideEffects;
+    bool32_t                                    supportsDynamicUniformBufferArrayIndexing;
+    // optional features
+    bool32_t                                    supportsDynamicStorageBufferArrayIndexing;
+    bool32_t                                    supportsDynamicStorageImageArrayIndexing;
+    bool32_t                                    supportsShaderFloat64;
+    bool32_t                                    supportsDepthBounds;
+    bool32_t                                    supportsWideLines;
+    bool32_t                                    supportsTextureCompressionETC2;
+    bool32_t                                    supportsTextureCompressionASTC_LDR;
+    bool32_t                                    supportsTextureCompressionBC;
+} VkPhysicalDeviceFeatures;
+
+typedef struct VkPhysicalDeviceLimits_
+{
+    uint32_t           maxImageDimensions;
+    uint32_t           maxImageDepth;
+    uint32_t           maxImageArrayLayers;
+    // <lots more>
+} VkPhysicalDeviceLimits;
+
+
 typedef struct VkPhysicalDevicePerformance_
 {
     float                                       maxDeviceClock;
@@ -1282,6 +1317,7 @@
     const VkDeviceQueueCreateInfo*              pRequestedQueues;
     uint32_t                                    extensionCount;
     const VkExtensionProperties*                pEnabledExtensions;         // Indicate extensions to enable by index value
+    const VkPhysicalDeviceFeatures*             pEnabledFeatures;
     VkDeviceCreateFlags                         flags;                      // Device creation flags
 } VkDeviceCreateInfo;
 
@@ -2009,6 +2045,9 @@
 typedef VkResult (VKAPI *PFN_vkDestroyInstance)(VkInstance instance);
 typedef VkResult (VKAPI *PFN_vkEnumeratePhysicalDevices)(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices);
 typedef VkResult (VKAPI *PFN_vkGetPhysicalDeviceInfo)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceInfoType infoType, size_t* pDataSize, void* pData);
+typedef VkResult (VKAPI *PFN_vkGetPhysicalDeviceFeatures)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures* pFeatures);
+typedef VkResult (VKAPI *PFN_vkGetPhysicalDeviceFormatInfo)(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties *pFormatInfo);
+typedef VkResult (VKAPI *PFN_vkGetPhysicalDeviceLimits)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceLimits* pLimits);
 typedef void *   (VKAPI *PFN_vkGetInstanceProcAddr)(VkInstance instance, const char * pName);
 typedef void *   (VKAPI *PFN_vkGetDeviceProcAddr)(VkDevice device, const char * pName);
 typedef VkResult (VKAPI *PFN_vkCreateDevice)(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, VkDevice* pDevice);
@@ -2043,7 +2082,6 @@
 typedef VkResult (VKAPI *PFN_vkResetEvent)(VkDevice device, VkEvent event);
 typedef VkResult (VKAPI *PFN_vkCreateQueryPool)(VkDevice device, const VkQueryPoolCreateInfo* pCreateInfo, VkQueryPool* pQueryPool);
 typedef VkResult (VKAPI *PFN_vkGetQueryPoolResults)(VkDevice device, VkQueryPool queryPool, uint32_t startQuery, uint32_t queryCount, size_t* pDataSize, void* pData, VkQueryResultFlags flags);
-typedef VkResult (VKAPI *PFN_vkGetFormatInfo)(VkDevice device, VkFormat format, VkFormatInfoType infoType, size_t* pDataSize, void* pData);
 typedef VkResult (VKAPI *PFN_vkCreateBuffer)(VkDevice device, const VkBufferCreateInfo* pCreateInfo, VkBuffer* pBuffer);
 typedef VkResult (VKAPI *PFN_vkCreateBufferView)(VkDevice device, const VkBufferViewCreateInfo* pCreateInfo, VkBufferView* pView);
 typedef VkResult (VKAPI *PFN_vkCreateImage)(VkDevice device, const VkImageCreateInfo* pCreateInfo, VkImage* pImage);
@@ -2133,6 +2171,20 @@
     size_t*                                     pDataSize,
     void*                                       pData);
 
+VkResult VKAPI vkGetPhysicalDeviceFeatures(
+    VkPhysicalDevice                            physicalDevice,
+    VkPhysicalDeviceFeatures*                   pFeatures);
+
+VkResult VKAPI vkGetPhysicalDeviceFormatInfo(
+    VkPhysicalDevice                            physicalDevice,
+    VkFormat                                    format,
+    VkFormatProperties*                         pFormatInfo);
+
+VkResult VKAPI vkGetPhysicalDeviceLimits(
+    VkPhysicalDevice                            physicalDevice,
+    VkPhysicalDeviceLimits*                     pLimits);
+
+
 void * VKAPI vkGetInstanceProcAddr(
     VkInstance                                  instance,
     const char*                                 pName);
@@ -2330,15 +2382,6 @@
     void*                                       pData,
     VkQueryResultFlags                          flags);
 
-// Format capabilities
-
-VkResult VKAPI vkGetFormatInfo(
-    VkDevice                                    device,
-    VkFormat                                    format,
-    VkFormatInfoType                            infoType,
-    size_t*                                     pDataSize,
-    void*                                       pData);
-
 // Buffer functions
 
 VkResult VKAPI vkCreateBuffer(
diff --git a/layers/basic.cpp b/layers/basic.cpp
index d6ea963..59ec08d 100644
--- a/layers/basic.cpp
+++ b/layers/basic.cpp
@@ -133,11 +133,11 @@
     return res;
 }
 
-VK_LAYER_EXPORT VkResult VKAPI vkGetFormatInfo(VkDevice device, VkFormat format, VkFormatInfoType infoType, size_t* pDataSize, void* pData)
+VK_LAYER_EXPORT VkResult VKAPI vkGetPhysicalDeviceFormatInfo(VkPhysicalDevice gpu, VkFormat format, VkFormatProperties *pFormatInfo)
 {
-    printf("At start of wrapped vkGetFormatInfo() call w/ device: %p\n", (void*)device);
-    VkResult result = device_dispatch_table(device)->GetFormatInfo(device, format, infoType, pDataSize, pData);
-    printf("Completed wrapped vkGetFormatInfo() call w/ device: %p\n", (void*)device);
+    printf("At start of wrapped vkGetPhysicalDeviceFormatInfo() call w/ gpu: %p\n", (void*)gpu);
+    VkResult result = instance_dispatch_table(gpu)->GetPhysicalDeviceFormatInfo(gpu, format, pFormatInfo);
+    printf("Completed wrapped vkGetPhysicalDeviceFormatInfo() call w/ gpu: %p\n", (void*)gpu);
     return result;
 }
 
@@ -152,8 +152,6 @@
         return (void *) vkGetDeviceProcAddr;
     }
 
-    if (!strcmp("vkGetFormatInfo", pName))
-        return (void *) vkGetFormatInfo;
     if (!strcmp("vkDestroyDevice", pName))
         return (void *) vkDestroyDevice;
     if (!strcmp("vkLayerExtension1", pName))
@@ -176,6 +174,8 @@
         initInstanceTable((const VkBaseLayerObject *) instance);
         return (void *) vkGetInstanceProcAddr;
     }
+    if (!strcmp("vkGetPhysicalDeviceFormatInfo", pName))
+        return (void *) vkGetPhysicalDeviceFormatInfo;
 
     if (!strcmp("vkDestroyInstance", pName))
         return (void *) vkDestroyInstance;
diff --git a/layers/image.cpp b/layers/image.cpp
index cac66a5..28caa38 100644
--- a/layers/image.cpp
+++ b/layers/image.cpp
@@ -46,6 +46,7 @@
 typedef struct _layer_data {
     debug_report_data *report_data;
     VkDbgMsgCallback logging_callback;
+    VkPhysicalDevice physicalDevice;
 } layer_data;
 
 static std::unordered_map<void*, layer_data*> layer_data_map;
@@ -177,6 +178,7 @@
         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);
+        device_data->physicalDevice = physicalDevice;
     }
 
     return result;
@@ -293,10 +295,10 @@
 {
     if(pCreateInfo->format != VK_FORMAT_UNDEFINED)
     {
+        layer_data *device_data = (layer_data *) mdd(device);
         VkFormatProperties properties;
-        size_t size = sizeof(properties);
-        VkResult result = get_dispatch_table(image_device_table_map, device)->GetFormatInfo(device, pCreateInfo->format,
-            VK_FORMAT_INFO_TYPE_PROPERTIES, &size, &properties);
+        VkResult result = get_dispatch_table(image_instance_table_map, device_data->physicalDevice)->GetPhysicalDeviceFormatInfo(
+                device_data->physicalDevice, pCreateInfo->format, &properties);
         if(result != VK_SUCCESS)
         {
             char const str[] = "vkCreateImage parameter, VkFormat pCreateInfo->format, cannot be validated";
@@ -321,10 +323,10 @@
     {
         if(pCreateInfo->pColorFormats[i] != VK_FORMAT_UNDEFINED)
         {
+            layer_data *device_data = (layer_data *) mdd(device);
             VkFormatProperties properties;
-            size_t size = sizeof(properties);
-            VkResult result = get_dispatch_table(image_device_table_map, device)->GetFormatInfo(device, pCreateInfo->pColorFormats[i],
-                VK_FORMAT_INFO_TYPE_PROPERTIES, &size, &properties);
+            VkResult result = get_dispatch_table(image_instance_table_map, device_data->physicalDevice)->GetPhysicalDeviceFormatInfo(
+                    device_data->physicalDevice, pCreateInfo->pColorFormats[i], &properties);
             if(result != VK_SUCCESS)
             {
                 std::stringstream ss;
@@ -384,10 +386,10 @@
 
     if(pCreateInfo->depthStencilFormat != VK_FORMAT_UNDEFINED)
     {
+        layer_data *device_data = (layer_data *) mdd(device);
         VkFormatProperties properties;
-        size_t size = sizeof(properties);
-        VkResult result = get_dispatch_table(image_device_table_map, device)->GetFormatInfo(device, pCreateInfo->depthStencilFormat,
-            VK_FORMAT_INFO_TYPE_PROPERTIES, &size, &properties);
+        VkResult result = get_dispatch_table(image_instance_table_map, device_data->physicalDevice)->GetPhysicalDeviceFormatInfo(
+                device_data->physicalDevice, pCreateInfo->depthStencilFormat, &properties);
         if(result != VK_SUCCESS)
         {
             char const str[] = "vkCreateRenderPass parameter, VkFormat pCreateInfo->depthStencilFormat, cannot be validated";
diff --git a/layers/param_checker.cpp b/layers/param_checker.cpp
index 4d05ba1..822cb42 100644
--- a/layers/param_checker.cpp
+++ b/layers/param_checker.cpp
@@ -644,18 +644,14 @@
     return result;
 }
 
-VK_LAYER_EXPORT VkResult VKAPI vkGetFormatInfo(VkDevice device, VkFormat format, VkFormatInfoType infoType, size_t* pDataSize, void* pData)
+VK_LAYER_EXPORT VkResult VKAPI vkGetPhysicalDeviceFormatInfo(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties *pFormatInfo)
 {
     char str[1024];
     if (!validate_VkFormat(format)) {
-        sprintf(str, "Parameter format to function GetFormatInfo has invalid value of %i.", (int)format);
+        sprintf(str, "Parameter format to function GetPhysicalDeviceFormatInfo has invalid value of %i.", (int)format);
         layerCbMsg(VK_DBG_REPORT_ERROR_BIT, (VkObjectType) 0, NULL, 0, 1, "PARAMCHECK", str);
     }
-    if (!validate_VkFormatInfoType(infoType)) {
-        sprintf(str, "Parameter infoType to function GetFormatInfo has invalid value of %i.", (int)infoType);
-        layerCbMsg(VK_DBG_REPORT_ERROR_BIT, (VkObjectType) 0, NULL, 0, 1, "PARAMCHECK", str);
-    }
-    VkResult result = device_dispatch_table(device)->GetFormatInfo(device, format, infoType, pDataSize, pData);
+    VkResult result = instance_dispatch_table(physicalDevice)->GetPhysicalDeviceFormatInfo(physicalDevice, format, pFormatInfo);
     return result;
 }
 
@@ -723,6 +719,7 @@
         return;
     }
 
+	/*
     VkFormatProperties properties;
     size_t size = sizeof(properties);
     VkResult result = device_dispatch_table(device)->GetFormatInfo(device, pCreateInfo->format,
@@ -742,6 +739,7 @@
         layerCbMsg(VK_DBG_REPORT_ERROR_BIT, (VkObjectType) 0, NULL, 0, 1, "PARAMCHECK", str);
         return;
     }
+	*/
 
     // TODO: Can we check device-specific limits?
     if (!vk_validate_vkextent3d(&pCreateInfo->extent))
@@ -1568,6 +1566,7 @@
             continue;
         }
 
+		/*
         VkFormatProperties properties;
         size_t size = sizeof(properties);
         VkResult result = device_dispatch_table(device)->GetFormatInfo(device, pCreateInfo->pColorFormats[i],
@@ -1589,6 +1588,7 @@
             layerCbMsg(VK_DBG_REPORT_ERROR_BIT, (VkObjectType) 0, NULL, 0, 1, "PARAMCHECK", ss.str().c_str());
             continue;
         }
+		*/
 
     }
 
@@ -1696,6 +1696,7 @@
         return;
     }
 
+	/*
     VkFormatProperties properties;
     size_t size = sizeof(properties);
     VkResult result = device_dispatch_table(device)->GetFormatInfo(device, pCreateInfo->depthStencilFormat,
@@ -1715,6 +1716,7 @@
         layerCbMsg(VK_DBG_REPORT_ERROR_BIT, (VkObjectType) 0, NULL, 0, 1, "PARAMCHECK", str);
         return;
     }
+	*/
 
     if(!validate_VkImageLayout(pCreateInfo->depthStencilLayout))
     {
@@ -1948,8 +1950,6 @@
         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"))
@@ -2102,6 +2102,8 @@
         return (void*) vkGetGlobalExtensionInfo;
     if (!strcmp(name, "GetPhysicalDeviceExtensionInfo"))
         return (void*) vkGetPhysicalDeviceExtensionInfo;
+    if (!strcmp(name, "GetPhysicalDeviceFormatInfo"))
+        return (void*) vkGetPhysicalDeviceFormatInfo;
 
     return NULL;
 }
diff --git a/loader/gpa_helper.h b/loader/gpa_helper.h
index 52afa9b..fd30055 100644
--- a/loader/gpa_helper.h
+++ b/loader/gpa_helper.h
@@ -107,8 +107,6 @@
         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"))
@@ -263,6 +261,12 @@
         return (void*) vkEnumeratePhysicalDevices;
     if (!strcmp(name, "GetPhysicalDeviceInfo"))
         return (void*) vkGetPhysicalDeviceInfo;
+    if (!strcmp(name, "GetPhysicalDeviceFeatures"))
+        return (void*) vkGetPhysicalDeviceFeatures;
+    if (!strcmp(name, "GetPhysicalDeviceFormatInfo"))
+        return (void*) vkGetPhysicalDeviceFormatInfo;
+    if (!strcmp(name, "GetPhysicalDeviceLimits"))
+        return (void*) vkGetPhysicalDeviceLimits;
     if (!strcmp(name, "GetInstanceProcAddr"))
         return (void*) vkGetInstanceProcAddr;
     if (!strcmp(name, "GetDeviceProcAddr"))
diff --git a/loader/loader.c b/loader/loader.c
index 57956ae..e940ef6 100644
--- a/loader/loader.c
+++ b/loader/loader.c
@@ -88,6 +88,9 @@
     .DestroyInstance = loader_DestroyInstance,
     .EnumeratePhysicalDevices = loader_EnumeratePhysicalDevices,
     .GetPhysicalDeviceInfo = loader_GetPhysicalDeviceInfo,
+    .GetPhysicalDeviceFeatures = loader_GetPhysicalDeviceFeatures,
+    .GetPhysicalDeviceFormatInfo = loader_GetPhysicalDeviceFormatInfo,
+    .GetPhysicalDeviceLimits = loader_GetPhysicalDeviceLimits,
     .CreateDevice = loader_CreateDevice,
     .GetPhysicalDeviceExtensionInfo = loader_GetPhysicalDeviceExtensionInfo,
     .DbgCreateMsgCallback = loader_DbgCreateMsgCallback,
@@ -718,6 +721,9 @@
     LOOKUP(DestroyInstance);
     LOOKUP(EnumeratePhysicalDevices);
     LOOKUP(GetPhysicalDeviceInfo);
+    LOOKUP(GetPhysicalDeviceFeatures);
+    LOOKUP(GetPhysicalDeviceFormatInfo);
+    LOOKUP(GetPhysicalDeviceLimits);
     LOOKUP(CreateDevice);
     LOOKUP(GetPhysicalDeviceExtensionInfo);
     LOOKUP(DbgCreateMsgCallback);
@@ -1699,6 +1705,49 @@
     return res;
 }
 
+VkResult loader_GetPhysicalDeviceFeatures(
+        VkPhysicalDevice                        physicalDevice,
+        VkPhysicalDeviceFeatures*               pFeatures)
+{
+    uint32_t gpu_index;
+    struct loader_icd *icd = loader_get_icd(physicalDevice, &gpu_index);
+    VkResult res = VK_ERROR_INITIALIZATION_FAILED;
+
+    if (icd->GetPhysicalDeviceFeatures)
+        res = icd->GetPhysicalDeviceFeatures(physicalDevice, pFeatures);
+
+    return res;
+}
+
+VkResult loader_GetPhysicalDeviceFormatInfo(
+        VkPhysicalDevice                        physicalDevice,
+        VkFormat                                format,
+        VkFormatProperties*                     pFormatInfo)
+{
+    uint32_t gpu_index;
+    struct loader_icd *icd = loader_get_icd(physicalDevice, &gpu_index);
+    VkResult res = VK_ERROR_INITIALIZATION_FAILED;
+
+    if (icd->GetPhysicalDeviceFormatInfo)
+        res = icd->GetPhysicalDeviceFormatInfo(physicalDevice, format, pFormatInfo);
+
+    return res;
+}
+
+VkResult loader_GetPhysicalDeviceLimits(
+        VkPhysicalDevice                        physicalDevice,
+        VkPhysicalDeviceLimits*                 pLimits)
+{
+    uint32_t gpu_index;
+    struct loader_icd *icd = loader_get_icd(physicalDevice, &gpu_index);
+    VkResult res = VK_ERROR_INITIALIZATION_FAILED;
+
+    if (icd->GetPhysicalDeviceLimits)
+        res = icd->GetPhysicalDeviceLimits(physicalDevice, pLimits);
+
+    return res;
+}
+
 VkResult loader_CreateDevice(
         VkPhysicalDevice                        gpu,
         const VkDeviceCreateInfo*               pCreateInfo,
diff --git a/loader/loader.h b/loader/loader.h
index 72a21d4..7019da8 100644
--- a/loader/loader.h
+++ b/loader/loader.h
@@ -117,6 +117,9 @@
     PFN_vkDestroyInstance DestroyInstance;
     PFN_vkEnumeratePhysicalDevices EnumeratePhysicalDevices;
     PFN_vkGetPhysicalDeviceInfo GetPhysicalDeviceInfo;
+    PFN_vkGetPhysicalDeviceFeatures GetPhysicalDeviceFeatures;
+    PFN_vkGetPhysicalDeviceFormatInfo GetPhysicalDeviceFormatInfo;
+    PFN_vkGetPhysicalDeviceLimits GetPhysicalDeviceLimits;
     PFN_vkCreateDevice CreateDevice;
     PFN_vkGetPhysicalDeviceExtensionInfo GetPhysicalDeviceExtensionInfo;
     PFN_vkDbgCreateMsgCallback DbgCreateMsgCallback;
@@ -320,12 +323,26 @@
         VkInstance                              instance,
         uint32_t*                               pPhysicalDeviceCount,
         VkPhysicalDevice*                       pPhysicalDevices);
+
 VkResult loader_GetPhysicalDeviceInfo(
         VkPhysicalDevice                        gpu,
         VkPhysicalDeviceInfoType                infoType,
         size_t*                                 pDataSize,
         void*                                   pData);
 
+VkResult loader_GetPhysicalDeviceFeatures(
+        VkPhysicalDevice                        physicalDevice,
+        VkPhysicalDeviceFeatures*               pFeatures);
+
+VkResult loader_GetPhysicalDeviceFormatInfo(
+        VkPhysicalDevice                        physicalDevice,
+        VkFormat                                format,
+        VkFormatProperties*                     pFormatInfo);
+
+VkResult loader_GetPhysicalDeviceLimits(
+        VkPhysicalDevice                        physicalDevice,
+        VkPhysicalDeviceLimits*                 pLimits);
+
 VkResult loader_GetPhysicalDeviceExtensionInfo(
         VkPhysicalDevice                        gpu,
         VkExtensionInfoType                     infoType,
diff --git a/loader/table_ops.h b/loader/table_ops.h
index 360406a..f1cbc22 100644
--- a/loader/table_ops.h
+++ b/loader/table_ops.h
@@ -66,7 +66,6 @@
     table->ResetEvent = (PFN_vkResetEvent) gpa(dev, "vkResetEvent");
     table->CreateQueryPool = (PFN_vkCreateQueryPool) gpa(dev, "vkCreateQueryPool");
     table->GetQueryPoolResults = (PFN_vkGetQueryPoolResults) gpa(dev, "vkGetQueryPoolResults");
-    table->GetFormatInfo = (PFN_vkGetFormatInfo) gpa(dev, "vkGetFormatInfo");
     table->CreateBuffer = (PFN_vkCreateBuffer) gpa(dev, "vkCreateBuffer");
     table->CreateBufferView = (PFN_vkCreateBufferView) gpa(dev, "vkCreateBufferView");
     table->CreateImage = (PFN_vkCreateImage) gpa(dev, "vkCreateImage");
@@ -210,8 +209,6 @@
         return (void *) table->CreateQueryPool;
     if (!strcmp(name, "GetQueryPoolResults"))
         return (void *) table->GetQueryPoolResults;
-    if (!strcmp(name, "GetFormatInfo"))
-        return (void *) table->GetFormatInfo;
     if (!strcmp(name, "CreateBuffer"))
         return (void *) table->CreateBuffer;
     if (!strcmp(name, "CreateBufferView"))
@@ -361,6 +358,9 @@
     table->DestroyInstance = (PFN_vkDestroyInstance) gpa(inst, "vkDestroyInstance");
     table->EnumeratePhysicalDevices = (PFN_vkEnumeratePhysicalDevices) gpa(inst, "vkEnumeratePhysicalDevices");
     table->GetPhysicalDeviceInfo = (PFN_vkGetPhysicalDeviceInfo) gpa(inst, "vkGetPhysicalDeviceInfo");
+    table->GetPhysicalDeviceFeatures = (PFN_vkGetPhysicalDeviceFeatures) gpa(inst, "vkGetPhysicalDeviceFeatures");
+    table->GetPhysicalDeviceFormatInfo = (PFN_vkGetPhysicalDeviceFormatInfo) gpa(inst, "vkGetPhysicalDeviceFormatInfo");
+    table->GetPhysicalDeviceLimits = (PFN_vkGetPhysicalDeviceLimits) gpa(inst, "vkGetPhysicalDeviceLimits");
     table->CreateDevice = (PFN_vkCreateDevice) gpa(inst, "vkCreateDevice");
     table->GetPhysicalDeviceExtensionInfo = (PFN_vkGetPhysicalDeviceExtensionInfo) gpa(inst, "vkGetPhysicalDeviceExtensionInfo");
 }
@@ -390,6 +390,12 @@
         return (void *) table->EnumeratePhysicalDevices;
     if (!strcmp(name, "GetPhysicalDeviceInfo"))
         return (void *) table->GetPhysicalDeviceInfo;
+    if (!strcmp(name, "GetPhysicalDeviceFeatures"))
+        return (void *) table->GetPhysicalDeviceFeatures;
+    if (!strcmp(name, "GetPhysicalDeviceFormatInfo"))
+        return (void *) table->GetPhysicalDeviceFormatInfo;
+    if (!strcmp(name, "GetPhysicalDeviceLimits"))
+        return (void *) table->GetPhysicalDeviceLimits;
     if (!strcmp(name, "GetInstanceProcAddr"))
         return (void *) table->GetInstanceProcAddr;
     if (!strcmp(name, "CreateDevice"))
diff --git a/loader/trampoline.c b/loader/trampoline.c
index c5eb01a..0a1a140 100644
--- a/loader/trampoline.c
+++ b/loader/trampoline.c
@@ -164,6 +164,55 @@
     return res;
 }
 
+LOADER_EXPORT VkResult VKAPI vkGetPhysicalDeviceFeatures(
+                                            VkPhysicalDevice gpu,
+                                            VkPhysicalDeviceFeatures *pFeatures)
+{
+    const VkLayerInstanceDispatchTable *disp;
+    VkResult res;
+
+    disp = loader_get_instance_dispatch(gpu);
+
+    loader_platform_thread_lock_mutex(&loader_lock);
+    res = disp->GetPhysicalDeviceFeatures(gpu, pFeatures);
+    loader_platform_thread_unlock_mutex(&loader_lock);
+
+    return res;
+}
+
+LOADER_EXPORT VkResult VKAPI vkGetPhysicalDeviceFormatInfo(
+                                            VkPhysicalDevice gpu,
+                                            VkFormat format,
+                                            VkFormatProperties *pFormatInfo)
+{
+    const VkLayerInstanceDispatchTable *disp;
+    VkResult res;
+
+    disp = loader_get_instance_dispatch(gpu);
+
+    loader_platform_thread_lock_mutex(&loader_lock);
+    res = disp->GetPhysicalDeviceFormatInfo(gpu, format, pFormatInfo);
+    loader_platform_thread_unlock_mutex(&loader_lock);
+
+    return res;
+}
+
+LOADER_EXPORT VkResult VKAPI vkGetPhysicalDeviceLimits(
+                                            VkPhysicalDevice gpu,
+                                            VkPhysicalDeviceLimits *pLimits)
+{
+    const VkLayerInstanceDispatchTable *disp;
+    VkResult res;
+
+    disp = loader_get_instance_dispatch(gpu);
+
+    loader_platform_thread_lock_mutex(&loader_lock);
+    res = disp->GetPhysicalDeviceLimits(gpu, pLimits);
+    loader_platform_thread_unlock_mutex(&loader_lock);
+
+    return res;
+}
+
 LOADER_EXPORT VkResult VKAPI vkCreateDevice(
                                         VkPhysicalDevice gpu,
                                         const VkDeviceCreateInfo* pCreateInfo,
@@ -468,15 +517,6 @@
     return disp->GetQueryPoolResults(device, queryPool, startQuery, queryCount, pDataSize, pData, flags);
 }
 
-LOADER_EXPORT VkResult VKAPI vkGetFormatInfo(VkDevice device, VkFormat format, VkFormatInfoType infoType, size_t* pDataSize, void* pData)
-{
-    const VkLayerDispatchTable *disp;
-
-    disp = loader_get_dispatch(device);
-
-    return disp->GetFormatInfo(device, format, infoType, pDataSize, pData);
-}
-
 LOADER_EXPORT VkResult VKAPI vkCreateBuffer(VkDevice device, const VkBufferCreateInfo* pCreateInfo, VkBuffer* pBuffer)
 {
     const VkLayerDispatchTable *disp;
diff --git a/tests/blit_tests.cpp b/tests/blit_tests.cpp
index b2a13ec..058f47f 100644
--- a/tests/blit_tests.cpp
+++ b/tests/blit_tests.cpp
@@ -1337,13 +1337,11 @@
          it != test_formats_.end(); it++) {
         const float color[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
         VkFormatProperties props;
-        size_t size = sizeof(props);
         VkResult err;
 
-        err = vkGetFormatInfo(dev_.obj(), it->format,
-                               VK_FORMAT_INFO_TYPE_PROPERTIES,
-                               &size, &props);
+        err = vkGetPhysicalDeviceFormatInfo(dev_.gpu().obj(), it->format, &props);
         ASSERT_EQ(err, VK_SUCCESS);
+
         if (it->tiling == VK_IMAGE_TILING_LINEAR && !(props.linearTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))
             continue;
 
@@ -1387,13 +1385,11 @@
          it != test_formats_.end(); it++) {
         const uint32_t color[4] = { 0x11111111, 0x22222222, 0x33333333, 0x44444444 };
         VkFormatProperties props;
-        size_t size = sizeof(props);
         VkResult err;
 
-        err = vkGetFormatInfo(dev_.obj(), it->format,
-                               VK_FORMAT_INFO_TYPE_PROPERTIES,
-                               &size, &props);
+        err = vkGetPhysicalDeviceFormatInfo(dev_.gpu().obj(), it->format, &props);
         ASSERT_EQ(err, VK_SUCCESS);
+
         if (it->tiling == VK_IMAGE_TILING_LINEAR && !(props.linearTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))
             continue;
 
@@ -1571,13 +1567,11 @@
     for (std::vector<vk_testing::Device::Format>::const_iterator it = test_formats_.begin();
          it != test_formats_.end(); it++) {
         VkFormatProperties props;
-        size_t size = sizeof(props);
         VkResult err;
 
-        err = vkGetFormatInfo(dev_.obj(), it->format,
-                               VK_FORMAT_INFO_TYPE_PROPERTIES,
-                               &size, &props);
+        err = vkGetPhysicalDeviceFormatInfo(dev_.gpu().obj(), it->format, &props);
         ASSERT_EQ(err, VK_SUCCESS);
+
         if (it->tiling == VK_IMAGE_TILING_LINEAR && !(props.linearTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT))
             continue;
 
diff --git a/tests/image_tests.cpp b/tests/image_tests.cpp
index 7a6fbd5..e28ff61 100644
--- a/tests/image_tests.cpp
+++ b/tests/image_tests.cpp
@@ -124,7 +124,6 @@
 {
     VkResult err;
     uint32_t mipCount;
-    size_t size;
     VkFormat fmt;
     VkFormatProperties image_fmt;
 
@@ -149,10 +148,7 @@
      * amount of data may vary and that doesn't work well for using a
      * fixed structure.
      */
-    size = sizeof(image_fmt);
-    err = vkGetFormatInfo(this->device(), fmt,
-                           VK_FORMAT_INFO_TYPE_PROPERTIES,
-                           &size, &image_fmt);
+    err = vkGetPhysicalDeviceFormatInfo(this->objs[0], fmt, &image_fmt);
     ASSERT_VK_SUCCESS(err);
 
     //    typedef struct VkImageCreateInfo_
diff --git a/tests/init.cpp b/tests/init.cpp
index f353fad..cb0c445 100644
--- a/tests/init.cpp
+++ b/tests/init.cpp
@@ -350,7 +350,6 @@
     VkResult err;
     VkImage image;
     uint32_t w, h, mipCount;
-    size_t size;
     VkFormat fmt;
     VkFormatProperties image_fmt;
     size_t data_size;
@@ -379,10 +378,7 @@
      * fixed structure.
      */
 
-    size = sizeof(image_fmt);
-    err = vkGetFormatInfo(device(), fmt,
-                           VK_FORMAT_INFO_TYPE_PROPERTIES,
-                           &size, &image_fmt);
+    err = vkGetPhysicalDeviceFormatInfo(objs[m_device_id], fmt, &image_fmt);
     ASSERT_VK_SUCCESS(err);
 
 //    typedef struct VkImageCreateInfo_
diff --git a/tests/vkrenderframework.cpp b/tests/vkrenderframework.cpp
index b598be7..7c3fa4a 100644
--- a/tests/vkrenderframework.cpp
+++ b/tests/vkrenderframework.cpp
@@ -306,12 +306,9 @@
         VkImageObj *img = new VkImageObj(m_device);
 
         VkFormatProperties props;
-        size_t size = sizeof(props);
         VkResult err;
 
-        err = vkGetFormatInfo(m_device->obj(), m_render_target_fmt,
-            VK_FORMAT_INFO_TYPE_PROPERTIES,
-            &size, &props);
+        err = vkGetPhysicalDeviceFormatInfo(m_device->gpu().obj(), m_render_target_fmt, &props);
         ASSERT_VK_SUCCESS(err);
 
         if (props.linearTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) {
@@ -651,7 +648,6 @@
     VkFormatProperties image_fmt;
     VkImageTiling tiling;
     VkResult err;
-    size_t size;
 
     mipCount = 0;
 
@@ -664,10 +660,7 @@
         mipCount++;
     }
 
-    size = sizeof(image_fmt);
-    err = vkGetFormatInfo(m_device->obj(), fmt,
-        VK_FORMAT_INFO_TYPE_PROPERTIES,
-        &size, &image_fmt);
+    err = vkGetPhysicalDeviceFormatInfo(m_device->gpu().obj(), fmt, &image_fmt);
     ASSERT_VK_SUCCESS(err);
 
     if (requested_tiling == VK_IMAGE_TILING_LINEAR) {
diff --git a/tests/vktestbinding.cpp b/tests/vktestbinding.cpp
index d0526c3..1689f6a 100644
--- a/tests/vktestbinding.cpp
+++ b/tests/vktestbinding.cpp
@@ -417,10 +417,8 @@
 
 VkFormatProperties Device::format_properties(VkFormat format)
 {
-    const VkFormatInfoType type = VK_FORMAT_INFO_TYPE_PROPERTIES;
     VkFormatProperties data;
-    size_t size = sizeof(data);
-    if (!EXPECT(vkGetFormatInfo(obj(), format, type, &size, &data) == VK_SUCCESS && size == sizeof(data)))
+    if (!EXPECT(vkGetPhysicalDeviceFormatInfo(gpu().obj(), format, &data) == VK_SUCCESS))
         memset(&data, 0, sizeof(data));
 
     return data;
diff --git a/vulkan.py b/vulkan.py
index 8e6fd01..7fa074a 100755
--- a/vulkan.py
+++ b/vulkan.py
@@ -235,6 +235,19 @@
              Param("size_t*", "pDataSize"),
              Param("void*", "pData")]),
 
+        Proto("VkResult", "GetPhysicalDeviceFeatures",
+            [Param("VkPhysicalDevice", "physicalDevice"),
+             Param("VkPhysicalDeviceFeatures*", "pFeatures")]),
+
+        Proto("VkResult", "GetPhysicalDeviceFormatInfo",
+            [Param("VkPhysicalDevice", "physicalDevice"),
+             Param("VkFormat", "format"),
+             Param("VkFormatProperties*", "pFormatInfo")]),
+
+        Proto("VkResult", "GetPhysicalDeviceLimits",
+            [Param("VkPhysicalDevice", "physicalDevice"),
+             Param("VkPhysicalDeviceLimits*", "pLimits")]),
+
         Proto("void*", "GetInstanceProcAddr",
             [Param("VkInstance", "instance"),
              Param("const char*", "pName")]),
@@ -413,13 +426,6 @@
              Param("void*", "pData"),
              Param("VkQueryResultFlags", "flags")]),
 
-        Proto("VkResult", "GetFormatInfo",
-            [Param("VkDevice", "device"),
-             Param("VkFormat", "format"),
-             Param("VkFormatInfoType", "infoType"),
-             Param("size_t*", "pDataSize"),
-             Param("void*", "pData")]),
-
         Proto("VkResult", "CreateBuffer",
             [Param("VkDevice", "device"),
              Param("const VkBufferCreateInfo*", "pCreateInfo"),