From e4cc52c05437bf5bfd62b536a58f9eab04b3d695 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Sat, 23 Jan 2021 05:12:43 -0600 Subject: [PATCH] vulkan: Add common extension tables Unlike the per-driver tables, these contain every extension ever and assume the maximum extension version. This later assumption is ok because Vulkan extension versions have only been used for something interesting once in the history of the API. If it happens again, we can afford a special case. This requires us to rework the extension table generation scripts somewhat because we want to use the same script for both common and per-driver codegen right now. To do this we add a "prefix" variable to go alongside "driver". Reviewed-by: Lionel Landwerlin Reviewed-by: Bas Nieuwenhuizen Part-of: --- src/vulkan/Android.mk | 23 ++++++-- src/vulkan/Makefile.sources | 4 +- src/vulkan/util/meson.build | 15 +++++- src/vulkan/util/vk_extensions.py | 37 +++++++++++++ src/vulkan/util/vk_extensions_gen.py | 80 +++++++++++++++++++++------- 5 files changed, 134 insertions(+), 25 deletions(-) diff --git a/src/vulkan/Android.mk b/src/vulkan/Android.mk index 4b1695abc65..57342ce6e22 100644 --- a/src/vulkan/Android.mk +++ b/src/vulkan/Android.mk @@ -38,7 +38,8 @@ intermediates := $(call local-generated-sources-dir) LOCAL_C_INCLUDES := \ $(MESA_TOP)/include/vulkan \ $(MESA_TOP)/src/vulkan/util \ - $(MESA_TOP)/src/gallium/include + $(MESA_TOP)/src/gallium/include \ + $(intermediates)/util \ ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 27; echo $$?), 0) LOCAL_C_INCLUDES += \ @@ -55,7 +56,7 @@ LOCAL_SRC_FILES := $(VULKAN_UTIL_FILES) $(VULKAN_WSI_FILES) vulkan_api_xml = $(MESA_TOP)/src/vulkan/registry/vk.xml -$(firstword $(LOCAL_GENERATED_SOURCES)): $(MESA_TOP)/src/vulkan/util/gen_enum_to_str.py \ +$(intermediates)/util/vk_enum_to_str.c: $(MESA_TOP)/src/vulkan/util/gen_enum_to_str.py \ $(vulkan_api_xml) @echo "target Generated: $(PRIVATE_MODULE) <= $(notdir $(@))" @mkdir -p $(dir $@) @@ -63,7 +64,23 @@ $(firstword $(LOCAL_GENERATED_SOURCES)): $(MESA_TOP)/src/vulkan/util/gen_enum_to --xml $(vulkan_api_xml) \ --outdir $(dir $@) -$(lastword $(LOCAL_GENERATED_SOURCES)): $(firstword $(LOCAL_GENERATED_SOURCES)) +$(intermediates)/util/vk_enum_to_str.h: $(intermediates)/util/vk_enum_to_str.c + +$(intermediates)/util/vk_extensions.c: $(MESA_TOP)/src/vulkan/util/vk_extensions_gen.py \ + $(vulkan_api_xml) + @echo "target Generated: $(PRIVATE_MODULE) <= $(notdir $(@))" + @mkdir -p $(dir $@) + $(hide) $(MESA_PYTHON2) $< \ + --xml $(vulkan_api_xml) \ + --out-c $@ + +$(intermediates)/util/vk_extensions.h: $(MESA_TOP)/src/vulkan/util/vk_extensions_gen.py \ + $(vulkan_api_xml) + @echo "target Generated: $(PRIVATE_MODULE) <= $(notdir $(@))" + @mkdir -p $(dir $@) + $(hide) $(MESA_PYTHON2) $< \ + --xml $(vulkan_api_xml) \ + --out-h $@ LOCAL_EXPORT_C_INCLUDE_DIRS := $(intermediates)/util diff --git a/src/vulkan/Makefile.sources b/src/vulkan/Makefile.sources index e17a043ac01..9c684e8f56b 100644 --- a/src/vulkan/Makefile.sources +++ b/src/vulkan/Makefile.sources @@ -39,4 +39,6 @@ VULKAN_UTIL_FILES := \ VULKAN_UTIL_GENERATED_FILES := \ util/vk_enum_to_str.c \ - util/vk_enum_to_str.h + util/vk_enum_to_str.h \ + util/vk_extensions.c \ + util/vk_extensions.h diff --git a/src/vulkan/util/meson.build b/src/vulkan/util/meson.build index f0078c90258..5545ac00234 100644 --- a/src/vulkan/util/meson.build +++ b/src/vulkan/util/meson.build @@ -45,9 +45,20 @@ vk_enum_to_str = custom_target( ], ) +vk_extensions = custom_target( + 'vk_extensions', + input : ['vk_extensions_gen.py', vk_api_xml], + output : ['vk_extensions.c', 'vk_extensions.h'], + command : [ + prog_python, '@INPUT0@', '--xml', '@INPUT1@', + '--out-c', '@OUTPUT0@', '--out-h', '@OUTPUT1@' + ], + dependencies : ['vk_extensions.py'], +) + libvulkan_util = static_library( 'vulkan_util', - [files_vulkan_util, vk_enum_to_str], + [files_vulkan_util, vk_enum_to_str, vk_extensions], include_directories : [inc_include, inc_src, inc_gallium], dependencies : [vulkan_wsi_deps, idep_mesautil], c_args : [vulkan_wsi_args], @@ -56,7 +67,7 @@ libvulkan_util = static_library( ) idep_vulkan_util_headers = declare_dependency( - sources : vk_enum_to_str[1], + sources : [vk_enum_to_str[1], vk_extensions[1]], include_directories : include_directories('.') ) diff --git a/src/vulkan/util/vk_extensions.py b/src/vulkan/util/vk_extensions.py index 07217a6586b..9a0329ca10a 100644 --- a/src/vulkan/util/vk_extensions.py +++ b/src/vulkan/util/vk_extensions.py @@ -63,6 +63,43 @@ class VkVersion: return self.__int_ver() > other.__int_ver() +# Sort the extension list the way we expect: KHR, then EXT, then vendors +# alphabetically. For digits, read them as a whole number sort that. +# eg.: VK_KHR_8bit_storage < VK_KHR_16bit_storage < VK_EXT_acquire_xlib_display +def extension_order(ext): + order = [] + for substring in re.split('(KHR|EXT|[0-9]+)', ext.name): + if substring == 'KHR': + order.append(1) + if substring == 'EXT': + order.append(2) + elif substring.isdigit(): + order.append(int(substring)) + else: + order.append(substring) + return order + +def get_all_exts_from_xml(xml): + """ Get a list of all Vulkan extensions. """ + + xml = et.parse(xml) + + extensions = [] + for ext_elem in xml.findall('.extensions/extension'): + supported = ext_elem.attrib['supported'] == 'vulkan' + name = ext_elem.attrib['name'] + if not supported and name != 'VK_ANDROID_native_buffer': + continue + version = None + for enum_elem in ext_elem.findall('.require/enum'): + if enum_elem.attrib['name'].endswith('_SPEC_VERSION'): + assert version is None + version = int(enum_elem.attrib['value']) + ext = Extension(name, version, True) + extensions.append(Extension(name, version, True)) + + return sorted(extensions, key=extension_order) + def init_exts_from_xml(xml, extensions, platform_defines): """ Walk the Vulkan XML and fill out extra extension information. """ diff --git a/src/vulkan/util/vk_extensions_gen.py b/src/vulkan/util/vk_extensions_gen.py index bbfb60b3d81..4c74b45485c 100644 --- a/src/vulkan/util/vk_extensions_gen.py +++ b/src/vulkan/util/vk_extensions_gen.py @@ -35,10 +35,15 @@ _TEMPLATE_H = Template(COPYRIGHT + """ #ifndef ${driver.upper()}_EXTENSIONS_H #define ${driver.upper()}_EXTENSIONS_H +#include + %for include in includes: #include "${include}" %endfor +%if type_prefix == 'vk' and driver != 'vk': +#include "vk_extensions.h" +%else: #define ${driver.upper()}_INSTANCE_EXTENSION_COUNT ${len(instance_extensions)} extern const VkExtensionProperties ${driver}_instance_extensions[]; @@ -54,8 +59,6 @@ struct ${driver}_instance_extension_table { }; }; -extern const struct ${driver}_instance_extension_table ${driver}_instance_extensions_supported; - #define ${driver.upper()}_DEVICE_EXTENSION_COUNT ${len(device_extensions)} @@ -71,19 +74,45 @@ struct ${driver}_device_extension_table { }; }; }; +%endif struct ${driver}_physical_device; +%if driver != 'vk': +extern const struct ${type_prefix}_instance_extension_table ${driver}_instance_extensions_supported; + void ${driver}_physical_device_get_supported_extensions(const struct ${driver}_physical_device *device, - struct ${driver}_device_extension_table *extensions); + struct ${type_prefix}_device_extension_table *extensions); +%endif #endif /* ${driver.upper()}_EXTENSIONS_H */ """) _TEMPLATE_C = Template(COPYRIGHT + """ +%if driver == 'vk': +#include "vk_object.h" +%else: #include "${driver}_private.h" +%endif +#include "${driver}_extensions.h" + +%if type_prefix != 'vk' or driver == 'vk': +const VkExtensionProperties ${driver}_instance_extensions[${driver.upper()}_INSTANCE_EXTENSION_COUNT] = { +%for ext in instance_extensions: + {"${ext.name}", ${ext.ext_version}}, +%endfor +}; + +const VkExtensionProperties ${driver}_device_extensions[${driver.upper()}_DEVICE_EXTENSION_COUNT] = { +%for ext in device_extensions: + {"${ext.name}", ${ext.ext_version}}, +%endfor +}; +%endif + +%if driver != 'vk': #include "vk_util.h" /* Convert the VK_USE_PLATFORM_* defines to booleans */ @@ -119,13 +148,7 @@ VkResult ${driver}_EnumerateInstanceVersion( return VK_SUCCESS; } -const VkExtensionProperties ${driver}_instance_extensions[${driver.upper()}_INSTANCE_EXTENSION_COUNT] = { -%for ext in instance_extensions: - {"${ext.name}", ${ext.ext_version}}, -%endfor -}; - -const struct ${driver}_instance_extension_table ${driver}_instance_extensions_supported = { +const struct ${type_prefix}_instance_extension_table ${driver}_instance_extensions_supported = { %for ext in instance_extensions: .${ext.name[3:]} = ${get_extension_condition(ext.name, ext.enable)}, %endfor @@ -149,25 +172,21 @@ ${driver}_physical_device_api_version(struct ${driver}_physical_device *device) return version; } -const VkExtensionProperties ${driver}_device_extensions[${driver.upper()}_DEVICE_EXTENSION_COUNT] = { -%for ext in device_extensions: - {"${ext.name}", ${ext.ext_version}}, -%endfor -}; - void ${driver}_physical_device_get_supported_extensions(const struct ${driver}_physical_device *device, - struct ${driver}_device_extension_table *extensions) + struct ${type_prefix}_device_extension_table *extensions) { - *extensions = (struct ${driver}_device_extension_table) { + *extensions = (struct ${type_prefix}_device_extension_table) { %for ext in device_extensions: .${ext.name[3:]} = ${get_extension_condition(ext.name, ext.enable)}, %endfor }; } +%endif """) -def gen_extensions(driver, xml_files, api_versions, max_api_version, extensions, out_c, out_h, includes = []): +def gen_extensions(driver, xml_files, api_versions, max_api_version, + extensions, out_c, out_h, includes = [], type_prefix = None): platform_defines = [] for filename in xml_files: init_exts_from_xml(filename, extensions, platform_defines) @@ -175,8 +194,12 @@ def gen_extensions(driver, xml_files, api_versions, max_api_version, extensions, for ext in extensions: assert ext.type == 'instance' or ext.type == 'device' + if type_prefix is None: + type_prefix = driver + template_env = { 'driver': driver, + 'type_prefix': type_prefix, 'API_VERSIONS': api_versions, 'MAX_API_VERSION': max_api_version, 'instance_extensions': [e for e in extensions if e.type == 'instance'], @@ -193,3 +216,22 @@ def gen_extensions(driver, xml_files, api_versions, max_api_version, extensions, if out_c: with open(out_c, 'w') as f: f.write(_TEMPLATE_C.render(**template_env)) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('--out-c', help='Output C file.') + parser.add_argument('--out-h', help='Output H file.') + parser.add_argument('--xml', + help='Vulkan API XML file.', + required=True, + action='append', + dest='xml_files') + args = parser.parse_args() + + extensions = [] + for filename in args.xml_files: + extensions += get_all_exts_from_xml(filename) + + gen_extensions('vk', args.xml_files, None, None, + extensions, args.out_c, args.out_h, [])