anv: Autogenerate extension query and lookup
authorJason Ekstrand <jason.ekstrand@intel.com>
Fri, 14 Jul 2017 05:50:30 +0000 (22:50 -0700)
committerJason Ekstrand <jason.ekstrand@intel.com>
Tue, 1 Aug 2017 18:12:41 +0000 (11:12 -0700)
As time goes on, extension advertising is going to get more complex.
Today, we either implement an extension or we don't.  However, in the
future, whether or not we advertise an extension will depend on kernel
or hardware features.  This commit introduces a python codegen framework
that generates the anv_EnumerateFooExtensionProperties functions as well
as a pair of anv_foo_extension_supported functions for querying for the
support of a given extension string.  Each extension has an "enable"
predicate that is any valid C expression.  For device extensions, the
physical device is available as "device" so the expression could be
something such as "device->has_kernel_feature".  For instance
extensions, the only option is VK_USE_PLATFORM defines.

This mechanism also means that we have a single one-line-per-entry table
for all extension declarations instead of the two tables we had in
anv_device.c and the one we had in anv_entrypoints_gen.py.  The Python
code is smart and uses the XML to determine whether an extension is an
instance extension or device extension.

Reviewed-by: Emil Velikov <emil.velikov@collabora.com>
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
src/intel/Android.vulkan.mk
src/intel/Makefile.sources
src/intel/Makefile.vulkan.am
src/intel/vulkan/anv_device.c
src/intel/vulkan/anv_extensions.py
src/intel/vulkan/anv_private.h

index 398f2e7cd0783686a1f555ff8698d2b1f66f7c26..449d1fc83a89b78ce72933d9d8d38e20aada757e 100644 (file)
@@ -25,6 +25,8 @@ include $(LOCAL_PATH)/Makefile.sources
 
 VK_ENTRYPOINTS_SCRIPT := $(MESA_PYTHON2) $(LOCAL_PATH)/vulkan/anv_entrypoints_gen.py
 
+VK_EXTENSIONS_SCRIPT := $(MESA_PYTHON2) $(LOCAL_PATH)/vulkan/anv_extensions.py
+
 VULKAN_COMMON_INCLUDES := \
        $(MESA_TOP)/src/mapi \
        $(MESA_TOP)/src/gallium/auxiliary \
@@ -53,6 +55,7 @@ LOCAL_C_INCLUDES := \
        $(VULKAN_COMMON_INCLUDES)
 
 LOCAL_GENERATED_SOURCES += $(intermediates)/vulkan/anv_entrypoints.h
+LOCAL_GENERATED_SOURCES += $(intermediates)/vulkan/anv_extensions.c
 LOCAL_GENERATED_SOURCES += $(intermediates)/vulkan/dummy.c
 
 $(intermediates)/vulkan/dummy.c:
@@ -213,6 +216,12 @@ $(intermediates)/vulkan/anv_entrypoints.c:
                --xml $(MESA_TOP)/src/vulkan/registry/vk.xml \
                --outdir $(dir $@)
 
+$(intermediates)/vulkan/anv_extensions.c:
+       @mkdir -p $(dir $@)
+       $(VK_EXTENSIONS_SCRIPT) \
+               --xml $(MESA_TOP)/src/vulkan/registry/vk.xml \
+               --out $@
+
 LOCAL_SHARED_LIBRARIES := libdrm
 
 include $(MESA_COMMON_MK)
index 2b3065e3d2f0f2964c1e4b6dda9417a19777dfe7..075ee864f49d3236ec8246a60b01e714e7b05475 100644 (file)
@@ -240,7 +240,8 @@ VULKAN_GEM_STUB_FILES := \
 
 VULKAN_GENERATED_FILES := \
        vulkan/anv_entrypoints.c \
-       vulkan/anv_entrypoints.h
+       vulkan/anv_entrypoints.h \
+       vulkan/anv_extensions.c
 
 VULKAN_GENX_FILES := \
        vulkan/genX_blorp_exec.c \
index 98fbfc8c0e225618b3e6c146fd02feb1aa1096af..f91fdc62d423eb76f199491eb4e80bf0c7fd75fa 100644 (file)
@@ -31,6 +31,11 @@ vulkan/anv_entrypoints.c: vulkan/anv_entrypoints_gen.py \
                --xml $(vulkan_api_xml) --outdir $(builddir)/vulkan
 vulkan/anv_entrypoints.h: vulkan/anv_entrypoints.c
 
+vulkan/anv_extensions.c: vulkan/anv_extensions.py $(vulkan_api_xml)
+       $(MKDIR_GEN)
+       $(AM_V_GEN)$(PYTHON2) $(srcdir)/vulkan/anv_extensions.py \
+               --xml $(vulkan_api_xml) --out $@
+
 BUILT_SOURCES += $(VULKAN_GENERATED_FILES)
 CLEANFILES += \
        $(VULKAN_GENERATED_FILES) \
index c72a1006749c1bc98b8ae3085a675adb4de401c3..70b5cd1ec68cadc8705d3fc11c09609edaa184c3 100644 (file)
@@ -406,102 +406,6 @@ anv_physical_device_finish(struct anv_physical_device *device)
    close(device->local_fd);
 }
 
-static const VkExtensionProperties global_extensions[] = {
-   {
-      .extensionName = VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,
-      .specVersion = 1,
-   },
-   {
-      .extensionName = VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
-      .specVersion = 1,
-   },
-   {
-      .extensionName = VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME,
-      .specVersion = 1,
-   },
-   {
-      .extensionName = VK_KHR_SURFACE_EXTENSION_NAME,
-      .specVersion = 25,
-   },
-#ifdef VK_USE_PLATFORM_WAYLAND_KHR
-   {
-      .extensionName = VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME,
-      .specVersion = 6,
-   },
-#endif
-#ifdef VK_USE_PLATFORM_XCB_KHR
-   {
-      .extensionName = VK_KHR_XCB_SURFACE_EXTENSION_NAME,
-      .specVersion = 6,
-   },
-#endif
-#ifdef VK_USE_PLATFORM_XLIB_KHR
-   {
-      .extensionName = VK_KHR_XLIB_SURFACE_EXTENSION_NAME,
-      .specVersion = 6,
-   },
-#endif
-};
-
-static const VkExtensionProperties device_extensions[] = {
-   {
-      .extensionName = VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME,
-      .specVersion = 1,
-   },
-   {
-      .extensionName = VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME,
-      .specVersion = 1,
-   },
-   {
-      .extensionName = VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,
-      .specVersion = 1,
-   },
-   {
-      .extensionName = VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,
-      .specVersion = 1,
-   },
-   {
-      .extensionName = VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME,
-      .specVersion = 1,
-   },
-   {
-      .extensionName = VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME,
-      .specVersion = 1,
-   },
-   {
-      .extensionName = VK_KHR_MAINTENANCE1_EXTENSION_NAME,
-      .specVersion = 1,
-   },
-   {
-      .extensionName = VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME,
-      .specVersion = 1,
-   },
-   {
-      .extensionName = VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME,
-      .specVersion = 1,
-   },
-   {
-      .extensionName = VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME,
-      .specVersion = 1,
-   },
-   {
-      .extensionName = VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME,
-      .specVersion = 1,
-   },
-   {
-      .extensionName = VK_KHR_SWAPCHAIN_EXTENSION_NAME,
-      .specVersion = 68,
-   },
-   {
-      .extensionName = VK_KHR_VARIABLE_POINTERS_EXTENSION_NAME,
-      .specVersion = 1,
-   },
-   {
-      .extensionName = VK_KHX_MULTIVIEW_EXTENSION_NAME,
-      .specVersion = 1,
-   },
-};
-
 static void *
 default_alloc_func(void *pUserData, size_t size, size_t align,
                    VkSystemAllocationScope allocationScope)
@@ -556,15 +460,8 @@ VkResult anv_CreateInstance(
    }
 
    for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
-      bool found = false;
-      for (uint32_t j = 0; j < ARRAY_SIZE(global_extensions); j++) {
-         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i],
-                    global_extensions[j].extensionName) == 0) {
-            found = true;
-            break;
-         }
-      }
-      if (!found)
+      const char *ext_name = pCreateInfo->ppEnabledExtensionNames[i];
+      if (!anv_instance_extension_supported(ext_name))
          return vk_error(VK_ERROR_EXTENSION_NOT_PRESENT);
    }
 
@@ -1130,15 +1027,8 @@ VkResult anv_CreateDevice(
    assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO);
 
    for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
-      bool found = false;
-      for (uint32_t j = 0; j < ARRAY_SIZE(device_extensions); j++) {
-         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i],
-                    device_extensions[j].extensionName) == 0) {
-            found = true;
-            break;
-         }
-      }
-      if (!found)
+      const char *ext_name = pCreateInfo->ppEnabledExtensionNames[i];
+      if (!anv_physical_device_extension_supported(physical_device, ext_name))
          return vk_error(VK_ERROR_EXTENSION_NOT_PRESENT);
    }
 
@@ -1348,45 +1238,6 @@ void anv_DestroyDevice(
    vk_free(&device->alloc, device);
 }
 
-VkResult anv_EnumerateInstanceExtensionProperties(
-    const char*                                 pLayerName,
-    uint32_t*                                   pPropertyCount,
-    VkExtensionProperties*                      pProperties)
-{
-   if (pProperties == NULL) {
-      *pPropertyCount = ARRAY_SIZE(global_extensions);
-      return VK_SUCCESS;
-   }
-
-   *pPropertyCount = MIN2(*pPropertyCount, ARRAY_SIZE(global_extensions));
-   typed_memcpy(pProperties, global_extensions, *pPropertyCount);
-
-   if (*pPropertyCount < ARRAY_SIZE(global_extensions))
-      return VK_INCOMPLETE;
-
-   return VK_SUCCESS;
-}
-
-VkResult anv_EnumerateDeviceExtensionProperties(
-    VkPhysicalDevice                            physicalDevice,
-    const char*                                 pLayerName,
-    uint32_t*                                   pPropertyCount,
-    VkExtensionProperties*                      pProperties)
-{
-   if (pProperties == NULL) {
-      *pPropertyCount = ARRAY_SIZE(device_extensions);
-      return VK_SUCCESS;
-   }
-
-   *pPropertyCount = MIN2(*pPropertyCount, ARRAY_SIZE(device_extensions));
-   typed_memcpy(pProperties, device_extensions, *pPropertyCount);
-
-   if (*pPropertyCount < ARRAY_SIZE(device_extensions))
-      return VK_INCOMPLETE;
-
-   return VK_SUCCESS;
-}
-
 VkResult anv_EnumerateInstanceLayerProperties(
     uint32_t*                                   pPropertyCount,
     VkLayerProperties*                          pProperties)
index f325fe84da8ff36443968f1235792d3edf6dbecc..005a514eca89e6a698c071c87fe386c150df01f5 100644 (file)
@@ -63,3 +63,121 @@ EXTENSIONS = [
     Extension('VK_KHR_xlib_surface',                      6, 'VK_USE_PLATFORM_XLIB_KHR'),
     Extension('VK_KHX_multiview',                         1, True),
 ]
+
+def init_exts_from_xml(xml):
+    """ Walk the Vulkan XML and fill out extra extension information. """
+
+    xml = et.parse(xml)
+
+    ext_name_map = {}
+    for ext in EXTENSIONS:
+        ext_name_map[ext.name] = ext
+
+    for ext_elem in xml.findall('.extensions/extension'):
+        ext_name = ext_elem.attrib['name']
+        if ext_name not in ext_name_map:
+            continue
+        ext = ext_name_map[ext_name]
+
+        ext.type = ext_elem.attrib['type']
+
+    for ext in EXTENSIONS:
+        assert ext.type == 'instance' or ext.type == 'device'
+
+TEMPLATE = Template(COPYRIGHT + """
+#include "anv_private.h"
+
+#include "vk_util.h"
+
+/* Convert the VK_USE_PLATFORM_* defines to booleans */
+%for platform in ['ANDROID', 'WAYLAND', 'XCB', 'XLIB']:
+#ifdef VK_USE_PLATFORM_${platform}_KHR
+#   undef VK_USE_PLATFORM_${platform}_KHR
+#   define VK_USE_PLATFORM_${platform}_KHR true
+#else
+#   define VK_USE_PLATFORM_${platform}_KHR false
+#endif
+%endfor
+
+bool
+anv_instance_extension_supported(const char *name)
+{
+%for ext in instance_extensions:
+    if (strcmp(name, "${ext.name}") == 0)
+        return ${ext.enable};
+%endfor
+    return false;
+}
+
+VkResult anv_EnumerateInstanceExtensionProperties(
+    const char*                                 pLayerName,
+    uint32_t*                                   pPropertyCount,
+    VkExtensionProperties*                      pProperties)
+{
+    VK_OUTARRAY_MAKE(out, pProperties, pPropertyCount);
+
+%for ext in instance_extensions:
+    if (${ext.enable}) {
+        vk_outarray_append(&out, prop) {
+            *prop = (VkExtensionProperties) {
+                .extensionName = "${ext.name}",
+                .specVersion = ${ext.ext_version},
+            };
+        }
+    }
+%endfor
+
+    return vk_outarray_status(&out);
+}
+
+bool
+anv_physical_device_extension_supported(struct anv_physical_device *device,
+                                        const char *name)
+{
+%for ext in device_extensions:
+    if (strcmp(name, "${ext.name}") == 0)
+        return ${ext.enable};
+%endfor
+    return false;
+}
+
+VkResult anv_EnumerateDeviceExtensionProperties(
+    VkPhysicalDevice                            physicalDevice,
+    const char*                                 pLayerName,
+    uint32_t*                                   pPropertyCount,
+    VkExtensionProperties*                      pProperties)
+{
+    ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice);
+    VK_OUTARRAY_MAKE(out, pProperties, pPropertyCount);
+    (void)device;
+
+%for ext in device_extensions:
+    if (${ext.enable}) {
+        vk_outarray_append(&out, prop) {
+            *prop = (VkExtensionProperties) {
+                .extensionName = "${ext.name}",
+                .specVersion = ${ext.ext_version},
+            };
+        }
+    }
+%endfor
+
+    return vk_outarray_status(&out);
+}
+""")
+
+if __name__ == '__main__':
+    parser = argparse.ArgumentParser()
+    parser.add_argument('--out', help='Output C file.', required=True)
+    parser.add_argument('--xml', help='Vulkan API XML file.', required=True)
+    args = parser.parse_args()
+
+    init_exts_from_xml(args.xml)
+
+    template_env = {
+        'instance_extensions': [e for e in EXTENSIONS if e.type == 'instance'],
+        'device_extensions': [e for e in EXTENSIONS if e.type == 'device'],
+    }
+
+    with open(args.out, 'w') as f:
+        f.write(TEMPLATE.render(**template_env))
index 86c430397c80965d4306574515d3d284bfbb8686..818f6990dc7cd739b3f6efe630762aa420df9b67 100644 (file)
@@ -684,6 +684,10 @@ struct anv_instance {
 VkResult anv_init_wsi(struct anv_physical_device *physical_device);
 void anv_finish_wsi(struct anv_physical_device *physical_device);
 
+bool anv_instance_extension_supported(const char *name);
+bool anv_physical_device_extension_supported(struct anv_physical_device *dev,
+                                             const char *name);
+
 struct anv_queue {
     VK_LOADER_DATA                              _loader_data;