1# Copyright 2020 Intel Corporation 2# 3# Permission is hereby granted, free of charge, to any person obtaining a 4# copy of this software and associated documentation files (the 5# "Software"), to deal in the Software without restriction, including 6# without limitation the rights to use, copy, modify, merge, publish, 7# distribute, sub license, and/or sell copies of the Software, and to 8# permit persons to whom the Software is furnished to do so, subject to 9# the following conditions: 10# 11# The above copyright notice and this permission notice (including the 12# next paragraph) shall be included in all copies or substantial portions 13# of the Software. 14# 15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 18# IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 19# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 23import xml.etree.ElementTree as et 24 25from collections import OrderedDict, namedtuple 26 27# Mesa-local imports must be declared in meson variable 28# '{file_without_suffix}_depend_files'. 29from vk_extensions import get_all_required, filter_api 30 31EntrypointParam = namedtuple('EntrypointParam', 'type name decl len') 32 33class EntrypointBase: 34 def __init__(self, name): 35 assert name.startswith('vk') 36 self.name = name[2:] 37 self.alias = None 38 self.guard = None 39 self.entry_table_index = None 40 # Extensions which require this entrypoint 41 self.core_version = None 42 self.extensions = [] 43 44 def prefixed_name(self, prefix): 45 return prefix + '_' + self.name 46 47class Entrypoint(EntrypointBase): 48 def __init__(self, name, return_type, params): 49 super(Entrypoint, self).__init__(name) 50 self.return_type = return_type 51 self.params = params 52 self.guard = None 53 self.aliases = [] 54 self.disp_table_index = None 55 56 def is_physical_device_entrypoint(self): 57 return self.params[0].type in ('VkPhysicalDevice', ) 58 59 def is_device_entrypoint(self): 60 return self.params[0].type in ('VkDevice', 'VkCommandBuffer', 'VkQueue') 61 62 def decl_params(self, start=0): 63 return ', '.join(p.decl for p in self.params[start:]) 64 65 def call_params(self, start=0): 66 return ', '.join(p.name for p in self.params[start:]) 67 68class EntrypointAlias(EntrypointBase): 69 def __init__(self, name, entrypoint): 70 super(EntrypointAlias, self).__init__(name) 71 self.alias = entrypoint 72 entrypoint.aliases.append(self) 73 74 def is_physical_device_entrypoint(self): 75 return self.alias.is_physical_device_entrypoint() 76 77 def is_device_entrypoint(self): 78 return self.alias.is_device_entrypoint() 79 80 def prefixed_name(self, prefix): 81 return self.alias.prefixed_name(prefix) 82 83 @property 84 def params(self): 85 return self.alias.params 86 87 @property 88 def return_type(self): 89 return self.alias.return_type 90 91 @property 92 def disp_table_index(self): 93 return self.alias.disp_table_index 94 95 def decl_params(self): 96 return self.alias.decl_params() 97 98 def call_params(self): 99 return self.alias.call_params() 100 101def get_entrypoints(doc, api, beta): 102 """Extract the entry points from the registry.""" 103 entrypoints = OrderedDict() 104 105 required = get_all_required(doc, 'command', api, beta) 106 107 for command in doc.findall('./commands/command'): 108 if not filter_api(command, api): 109 continue 110 111 if 'alias' in command.attrib: 112 name = command.attrib['name'] 113 target = command.attrib['alias'] 114 e = EntrypointAlias(name, entrypoints[target]) 115 else: 116 name = command.find('./proto/name').text 117 ret_type = command.find('./proto/type').text 118 params = [EntrypointParam( 119 type=p.find('./type').text, 120 name=p.find('./name').text, 121 decl=''.join(p.itertext()), 122 len=p.attrib.get('altlen', p.attrib.get('len', None)) 123 ) for p in command.findall('./param') if filter_api(p, api)] 124 # They really need to be unique 125 e = Entrypoint(name, ret_type, params) 126 127 if name not in required: 128 continue 129 130 r = required[name] 131 e.core_version = r.core_version 132 e.extensions = r.extensions 133 e.guard = r.guard 134 135 assert name not in entrypoints, name 136 entrypoints[name] = e 137 138 return entrypoints.values() 139 140def get_entrypoints_from_xml(xml_files, beta, api='vulkan'): 141 entrypoints = [] 142 143 for filename in xml_files: 144 doc = et.parse(filename) 145 entrypoints += get_entrypoints(doc, api, beta) 146 147 return entrypoints 148