# 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 Extension, VkVersion 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, start=0): return ', '.join(p.decl for p in self.params[start:]) def call_params(self, start=0): return ', '.join(p.name for p in self.params[start:]) 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