diff --git a/src/vulkan/util/meson.build b/src/vulkan/util/meson.build index 234e7f1be25..d3040b60794 100644 --- a/src/vulkan/util/meson.build +++ b/src/vulkan/util/meson.build @@ -22,25 +22,29 @@ # dependency tracking. vk_extensions_depend_files = [ ] +vk_entrypoints_depend_files = [ + files('vk_extensions.py'), + vk_extensions_depend_files, +] vk_extensions_gen_depend_files = [ files('vk_extensions.py'), vk_extensions_depend_files, ] vk_dispatch_table_gen_depend_files = [ - files('vk_extensions.py'), - vk_extensions_depend_files, + files('vk_entrypoints.py'), + vk_entrypoints_depend_files, ] vk_entrypoints_gen_depend_files = [ - files('vk_dispatch_table_gen.py'), - vk_dispatch_table_gen_depend_files, + files('vk_entrypoints.py'), + vk_entrypoints_depend_files, ] vk_cmd_queue_gen_depend_files = [ - files('vk_dispatch_table_gen.py'), - vk_dispatch_table_gen_depend_files, + files('vk_entrypoints.py'), + vk_entrypoints_depend_files, ] vk_commands_gen_depend_files = [ - files('vk_dispatch_table_gen.py'), - vk_dispatch_table_gen_depend_files, + files('vk_entrypoints.py'), + vk_entrypoints_depend_files, ] vk_physical_device_features_gen_depend_files = [ ] diff --git a/src/vulkan/util/vk_cmd_queue_gen.py b/src/vulkan/util/vk_cmd_queue_gen.py index c15d368d993..1937d91b8b8 100644 --- a/src/vulkan/util/vk_cmd_queue_gen.py +++ b/src/vulkan/util/vk_cmd_queue_gen.py @@ -33,7 +33,7 @@ from mako.template import Template # Mesa-local imports must be declared in meson variable # '{file_without_suffix}_depend_files'. -from vk_dispatch_table_gen import get_entrypoints_from_xml, EntrypointParam +from vk_entrypoints import get_entrypoints_from_xml, EntrypointParam MANUAL_COMMANDS = ['CmdPushDescriptorSetKHR', # This script doesn't know how to copy arrays in structs in arrays 'CmdPushDescriptorSetWithTemplateKHR', # pData's size cannot be calculated from the xml diff --git a/src/vulkan/util/vk_commands_gen.py b/src/vulkan/util/vk_commands_gen.py index 4e281966eff..09f18813e4f 100644 --- a/src/vulkan/util/vk_commands_gen.py +++ b/src/vulkan/util/vk_commands_gen.py @@ -32,7 +32,7 @@ from mako.template import Template # Mesa-local imports must be declared in meson variable # '{file_without_suffix}_depend_files'. -from vk_dispatch_table_gen import get_entrypoints_from_xml, EntrypointParam +from vk_entrypoints import get_entrypoints_from_xml, EntrypointParam MANUAL_COMMANDS = ['CmdPushDescriptorSetKHR', # This script doesn't know how to copy arrays in structs in arrays 'CmdPushDescriptorSetWithTemplateKHR', # pData's size cannot be calculated from the xml diff --git a/src/vulkan/util/vk_dispatch_table_gen.py b/src/vulkan/util/vk_dispatch_table_gen.py index 8609a4df64a..9fef55141aa 100644 --- a/src/vulkan/util/vk_dispatch_table_gen.py +++ b/src/vulkan/util/vk_dispatch_table_gen.py @@ -27,14 +27,13 @@ COPYRIGHT = """\ import argparse import math import os -import xml.etree.ElementTree as et from collections import OrderedDict, namedtuple from mako.template import Template # Mesa-local imports must be declared in meson variable # '{file_without_suffix}_depend_files'. -from vk_extensions import * +from vk_entrypoints import get_entrypoints_from_xml # We generate a static hash table for entry point lookup # (vkGetProcAddress). We use a linear congruential generator for our hash @@ -741,153 +740,6 @@ class StringIntMap(object): self.collisions[min(level, 9)] += 1 self.mapping[h & self.hash_mask] = idx -EntrypointParam = namedtuple('EntrypointParam', 'type name decl len') - -class EntrypointBase: - def __init__(self, name): - assert name.startswith('vk') - self.name = name[2:] - self.alias = None - self.guard = None - self.entry_table_index = None - # Extensions which require this entrypoint - self.core_version = None - self.extensions = [] - - def prefixed_name(self, prefix): - return prefix + '_' + self.name - -class Entrypoint(EntrypointBase): - def __init__(self, name, return_type, params, guard=None): - super(Entrypoint, self).__init__(name) - self.return_type = return_type - self.params = params - self.guard = guard - self.aliases = [] - self.disp_table_index = None - - def is_physical_device_entrypoint(self): - return self.params[0].type in ('VkPhysicalDevice', ) - - def is_device_entrypoint(self): - return self.params[0].type in ('VkDevice', 'VkCommandBuffer', 'VkQueue') - - def decl_params(self): - return ', '.join(p.decl for p in self.params) - - def call_params(self): - return ', '.join(p.name for p in self.params) - -class EntrypointAlias(EntrypointBase): - def __init__(self, name, entrypoint): - super(EntrypointAlias, self).__init__(name) - self.alias = entrypoint - entrypoint.aliases.append(self) - - def is_physical_device_entrypoint(self): - return self.alias.is_physical_device_entrypoint() - - def is_device_entrypoint(self): - return self.alias.is_device_entrypoint() - - def prefixed_name(self, prefix): - return self.alias.prefixed_name(prefix) - - @property - def params(self): - return self.alias.params - - @property - def return_type(self): - return self.alias.return_type - - @property - def disp_table_index(self): - return self.alias.disp_table_index - - def decl_params(self): - return self.alias.decl_params() - - def call_params(self): - return self.alias.call_params() - -def get_entrypoints(doc, entrypoints_to_defines): - """Extract the entry points from the registry.""" - entrypoints = OrderedDict() - - for command in doc.findall('./commands/command'): - if 'alias' in command.attrib: - alias = command.attrib['name'] - target = command.attrib['alias'] - entrypoints[alias] = EntrypointAlias(alias, entrypoints[target]) - else: - name = command.find('./proto/name').text - ret_type = command.find('./proto/type').text - params = [EntrypointParam( - type=p.find('./type').text, - name=p.find('./name').text, - decl=''.join(p.itertext()), - len=p.attrib.get('len', None) - ) for p in command.findall('./param')] - guard = entrypoints_to_defines.get(name) - # They really need to be unique - assert name not in entrypoints - entrypoints[name] = Entrypoint(name, ret_type, params, guard) - - for feature in doc.findall('./feature'): - assert feature.attrib['api'] == 'vulkan' - version = VkVersion(feature.attrib['number']) - for command in feature.findall('./require/command'): - e = entrypoints[command.attrib['name']] - assert e.core_version is None - e.core_version = version - - for extension in doc.findall('.extensions/extension'): - if extension.attrib['supported'] != 'vulkan': - continue - - ext_name = extension.attrib['name'] - - ext = Extension(ext_name, 1, True) - ext.type = extension.attrib['type'] - - for command in extension.findall('./require/command'): - e = entrypoints[command.attrib['name']] - assert e.core_version is None - e.extensions.append(ext) - - return entrypoints.values() - - -def get_entrypoints_defines(doc): - """Maps entry points to extension defines.""" - entrypoints_to_defines = {} - - platform_define = {} - for platform in doc.findall('./platforms/platform'): - name = platform.attrib['name'] - define = platform.attrib['protect'] - platform_define[name] = define - - for extension in doc.findall('./extensions/extension[@platform]'): - platform = extension.attrib['platform'] - define = platform_define[platform] - - for entrypoint in extension.findall('./require/command'): - fullname = entrypoint.attrib['name'] - entrypoints_to_defines[fullname] = define - - return entrypoints_to_defines - -def get_entrypoints_from_xml(xml_files): - entrypoints = [] - - for filename in xml_files: - doc = et.parse(filename) - entrypoints += get_entrypoints(doc, get_entrypoints_defines(doc)) - - return entrypoints - def main(): parser = argparse.ArgumentParser() parser.add_argument('--out-c', help='Output C file.') diff --git a/src/vulkan/util/vk_entrypoints.py b/src/vulkan/util/vk_entrypoints.py new file mode 100644 index 00000000000..65f7948cb46 --- /dev/null +++ b/src/vulkan/util/vk_entrypoints.py @@ -0,0 +1,176 @@ +# Copyright 2020 Intel Corporation +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sub license, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice (including the +# next paragraph) shall be included in all copies or substantial portions +# of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +# IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR +# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +import xml.etree.ElementTree as et + +from collections import OrderedDict, namedtuple + +# Mesa-local imports must be declared in meson variable +# '{file_without_suffix}_depend_files'. +from vk_extensions import * + +EntrypointParam = namedtuple('EntrypointParam', 'type name decl len') + +class EntrypointBase: + def __init__(self, name): + assert name.startswith('vk') + self.name = name[2:] + self.alias = None + self.guard = None + self.entry_table_index = None + # Extensions which require this entrypoint + self.core_version = None + self.extensions = [] + + def prefixed_name(self, prefix): + return prefix + '_' + self.name + +class Entrypoint(EntrypointBase): + def __init__(self, name, return_type, params, guard=None): + super(Entrypoint, self).__init__(name) + self.return_type = return_type + self.params = params + self.guard = guard + self.aliases = [] + self.disp_table_index = None + + def is_physical_device_entrypoint(self): + return self.params[0].type in ('VkPhysicalDevice', ) + + def is_device_entrypoint(self): + return self.params[0].type in ('VkDevice', 'VkCommandBuffer', 'VkQueue') + + def decl_params(self): + return ', '.join(p.decl for p in self.params) + + def call_params(self): + return ', '.join(p.name for p in self.params) + +class EntrypointAlias(EntrypointBase): + def __init__(self, name, entrypoint): + super(EntrypointAlias, self).__init__(name) + self.alias = entrypoint + entrypoint.aliases.append(self) + + def is_physical_device_entrypoint(self): + return self.alias.is_physical_device_entrypoint() + + def is_device_entrypoint(self): + return self.alias.is_device_entrypoint() + + def prefixed_name(self, prefix): + return self.alias.prefixed_name(prefix) + + @property + def params(self): + return self.alias.params + + @property + def return_type(self): + return self.alias.return_type + + @property + def disp_table_index(self): + return self.alias.disp_table_index + + def decl_params(self): + return self.alias.decl_params() + + def call_params(self): + return self.alias.call_params() + +def get_entrypoints(doc, entrypoints_to_defines): + """Extract the entry points from the registry.""" + entrypoints = OrderedDict() + + for command in doc.findall('./commands/command'): + if 'alias' in command.attrib: + alias = command.attrib['name'] + target = command.attrib['alias'] + entrypoints[alias] = EntrypointAlias(alias, entrypoints[target]) + else: + name = command.find('./proto/name').text + ret_type = command.find('./proto/type').text + params = [EntrypointParam( + type=p.find('./type').text, + name=p.find('./name').text, + decl=''.join(p.itertext()), + len=p.attrib.get('len', None) + ) for p in command.findall('./param')] + guard = entrypoints_to_defines.get(name) + # They really need to be unique + assert name not in entrypoints + entrypoints[name] = Entrypoint(name, ret_type, params, guard) + + for feature in doc.findall('./feature'): + assert feature.attrib['api'] == 'vulkan' + version = VkVersion(feature.attrib['number']) + for command in feature.findall('./require/command'): + e = entrypoints[command.attrib['name']] + assert e.core_version is None + e.core_version = version + + for extension in doc.findall('.extensions/extension'): + if extension.attrib['supported'] != 'vulkan': + continue + + ext_name = extension.attrib['name'] + + ext = Extension(ext_name, 1, True) + ext.type = extension.attrib['type'] + + for command in extension.findall('./require/command'): + e = entrypoints[command.attrib['name']] + assert e.core_version is None + e.extensions.append(ext) + + return entrypoints.values() + + +def get_entrypoints_defines(doc): + """Maps entry points to extension defines.""" + entrypoints_to_defines = {} + + platform_define = {} + for platform in doc.findall('./platforms/platform'): + name = platform.attrib['name'] + define = platform.attrib['protect'] + platform_define[name] = define + + for extension in doc.findall('./extensions/extension[@platform]'): + platform = extension.attrib['platform'] + define = platform_define[platform] + + for entrypoint in extension.findall('./require/command'): + fullname = entrypoint.attrib['name'] + entrypoints_to_defines[fullname] = define + + return entrypoints_to_defines + +def get_entrypoints_from_xml(xml_files): + entrypoints = [] + + for filename in xml_files: + doc = et.parse(filename) + entrypoints += get_entrypoints(doc, get_entrypoints_defines(doc)) + + return entrypoints diff --git a/src/vulkan/util/vk_entrypoints_gen.py b/src/vulkan/util/vk_entrypoints_gen.py index def4eb5c354..be80dc9d184 100644 --- a/src/vulkan/util/vk_entrypoints_gen.py +++ b/src/vulkan/util/vk_entrypoints_gen.py @@ -29,7 +29,7 @@ from mako.template import Template # Mesa-local imports must be declared in meson variable # '{file_without_suffix}_depend_files'. -from vk_dispatch_table_gen import get_entrypoints_from_xml +from vk_entrypoints import get_entrypoints_from_xml TEMPLATE_H = Template(COPYRIGHT + """\ /* This file generated from ${filename}, don't edit directly. */