vulkan/device: Use vk_errorf to report missing features
authorJason Ekstrand <jason@jlekstrand.net>
Thu, 30 Sep 2021 16:41:15 +0000 (11:41 -0500)
committerMarge Bot <eric+marge@anholt.net>
Thu, 7 Oct 2021 20:51:36 +0000 (20:51 +0000)
With a tiny bit more code-gen, we can now not only throw the error but
also log back to the client exactly which feature was missing.

Reviewed-By: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13045>

src/vulkan/util/vk_physical_device_features.py

index 6b69390..b9665e5 100644 (file)
@@ -33,20 +33,21 @@ from mako.template import Template
 TEMPLATE_C = Template(COPYRIGHT + """
 /* This file generated from ${filename}, don't edit directly. */
 
+#include "vk_log.h"
 #include "vk_physical_device.h"
 #include "vk_util.h"
 
 static VkResult
-check_physical_device_features(const VkPhysicalDeviceFeatures *supported,
-                               const VkPhysicalDeviceFeatures *enabled)
+check_physical_device_features(struct vk_physical_device *physical_device,
+                               const VkPhysicalDeviceFeatures *supported,
+                               const VkPhysicalDeviceFeatures *enabled,
+                               const char *struct_name)
 {
-   const VkBool32 *supported_feature = (const VkBool32 *) supported;
-   const VkBool32 *enabled_feature = (const VkBool32 *) enabled;
-   unsigned num_features = sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32);
-   for (uint32_t i = 0; i < num_features; i++) {
-      if (enabled_feature[i] && !supported_feature[i])
-         return VK_ERROR_FEATURE_NOT_PRESENT;
-   }
+% for flag in pdev_features:
+   if (enabled->${flag} && !supported->${flag})
+      return vk_errorf(physical_device, VK_ERROR_FEATURE_NOT_PRESENT,
+                       "%s.%s not supported", struct_name, "${flag}");
+% endfor
 
    return VK_SUCCESS;
 }
@@ -96,8 +97,10 @@ vk_physical_device_check_device_features(struct vk_physical_device *physical_dev
 
    if (pCreateInfo->pEnabledFeatures) {
       VkResult result =
-        check_physical_device_features(&supported_features2.features,
-                                       pCreateInfo->pEnabledFeatures);
+        check_physical_device_features(physical_device,
+                                       &supported_features2.features,
+                                       pCreateInfo->pEnabledFeatures,
+                                       "VkPhysicalDeviceFeatures");
       if (result != VK_SUCCESS)
          return result;
    }
@@ -109,8 +112,10 @@ vk_physical_device_check_device_features(struct vk_physical_device *physical_dev
       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2: {
          const VkPhysicalDeviceFeatures2 *features2 = (const void *)feat;
          VkResult result =
-            check_physical_device_features(&supported_features2.features,
-                                           &features2->features);
+            check_physical_device_features(physical_device,
+                                           &supported_features2.features,
+                                           &features2->features,
+                                           "VkPhysicalDeviceFeatures2.features");
          if (result != VK_SUCCESS)
             return result;
         break;
@@ -121,7 +126,8 @@ vk_physical_device_check_device_features(struct vk_physical_device *physical_dev
          ${f.name} *b = (${f.name} *) feat;
 % for flag in f.vk_flags:
          if (b->${flag} && !a->${flag})
-            return VK_ERROR_FEATURE_NOT_PRESENT;
+            return vk_errorf(physical_device, VK_ERROR_FEATURE_NOT_PRESENT,
+                             "%s.%s not supported", "${f.name}", "${flag}");
 % endfor
          break;
       }
@@ -137,6 +143,21 @@ vk_physical_device_check_device_features(struct vk_physical_device *physical_dev
 
 Feature = namedtuple('Feature', 'name vk_type vk_flags')
 
+def get_pdev_features(doc):
+    for _type in doc.findall('./types/type'):
+        if _type.attrib.get('name') != 'VkPhysicalDeviceFeatures':
+            continue
+
+        flags = []
+
+        for p in _type.findall('./member'):
+            assert p.find('./type').text == 'VkBool32'
+            flags.append(p.find('./name').text)
+
+        return flags
+
+    return None
+
 def get_features(doc):
     features = OrderedDict()
 
@@ -182,13 +203,16 @@ def get_features(doc):
     return features.values()
 
 def get_features_from_xml(xml_files):
+    pdev_features = None
     features = []
 
     for filename in xml_files:
         doc = et.parse(filename)
         features += get_features(doc)
+        if not pdev_features:
+            pdev_features = get_pdev_features(doc)
 
-    return features
+    return pdev_features, features
 
 
 def main():
@@ -199,10 +223,11 @@ def main():
                         required=True, action='append', dest='xml_files')
     args = parser.parse_args()
 
-    features = get_features_from_xml(args.xml_files)
+    pdev_features, features = get_features_from_xml(args.xml_files)
 
     environment = {
         'filename': os.path.basename(__file__),
+        'pdev_features': pdev_features,
         'features': features,
     }