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 <lionel.g.landwerlin@intel.com>
Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8676>
This commit is contained in:
Jason Ekstrand 2021-01-23 05:12:43 -06:00 committed by Marge Bot
parent 5d6ac87d61
commit e4cc52c054
5 changed files with 134 additions and 25 deletions

View File

@ -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

View File

@ -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

View File

@ -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('.')
)

View File

@ -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. """

View File

@ -35,10 +35,15 @@ _TEMPLATE_H = Template(COPYRIGHT + """
#ifndef ${driver.upper()}_EXTENSIONS_H
#define ${driver.upper()}_EXTENSIONS_H
#include <stdbool.h>
%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, [])