1b8e80941Smrg# coding=utf-8 2b8e80941Smrg# 3b8e80941Smrg# Copyright © 2015, 2017 Intel Corporation 4b8e80941Smrg# 5b8e80941Smrg# Permission is hereby granted, free of charge, to any person obtaining a 6b8e80941Smrg# copy of this software and associated documentation files (the "Software"), 7b8e80941Smrg# to deal in the Software without restriction, including without limitation 8b8e80941Smrg# the rights to use, copy, modify, merge, publish, distribute, sublicense, 9b8e80941Smrg# and/or sell copies of the Software, and to permit persons to whom the 10b8e80941Smrg# Software is furnished to do so, subject to the following conditions: 11b8e80941Smrg# 12b8e80941Smrg# The above copyright notice and this permission notice (including the next 13b8e80941Smrg# paragraph) shall be included in all copies or substantial portions of the 14b8e80941Smrg# Software. 15b8e80941Smrg# 16b8e80941Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17b8e80941Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18b8e80941Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19b8e80941Smrg# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20b8e80941Smrg# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21b8e80941Smrg# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22b8e80941Smrg# IN THE SOFTWARE. 23b8e80941Smrg# 24b8e80941Smrg 25b8e80941Smrgimport argparse 26b8e80941Smrgimport functools 27b8e80941Smrgimport math 28b8e80941Smrgimport os 29b8e80941Smrgimport xml.etree.cElementTree as et 30b8e80941Smrg 31b8e80941Smrgfrom collections import OrderedDict, namedtuple 32b8e80941Smrgfrom mako.template import Template 33b8e80941Smrg 34b8e80941Smrgfrom tu_extensions import VkVersion, MAX_API_VERSION, EXTENSIONS 35b8e80941Smrg 36b8e80941Smrg# We generate a static hash table for entry point lookup 37b8e80941Smrg# (vkGetProcAddress). We use a linear congruential generator for our hash 38b8e80941Smrg# function and a power-of-two size table. The prime numbers are determined 39b8e80941Smrg# experimentally. 40b8e80941Smrg 41b8e80941Smrg# We currently don't use layers in tu, but keeping the ability for anv 42b8e80941Smrg# anyways, so we can use it for device groups. 43b8e80941SmrgLAYERS = [ 44b8e80941Smrg 'tu' 45b8e80941Smrg] 46b8e80941Smrg 47b8e80941SmrgTEMPLATE_H = Template("""\ 48b8e80941Smrg/* This file generated from ${filename}, don't edit directly. */ 49b8e80941Smrg 50b8e80941Smrgstruct tu_dispatch_table { 51b8e80941Smrg union { 52b8e80941Smrg void *entrypoints[${len(entrypoints)}]; 53b8e80941Smrg struct { 54b8e80941Smrg % for e in entrypoints: 55b8e80941Smrg % if e.guard is not None: 56b8e80941Smrg#ifdef ${e.guard} 57b8e80941Smrg PFN_${e.name} ${e.name}; 58b8e80941Smrg#else 59b8e80941Smrg void *${e.name}; 60b8e80941Smrg# endif 61b8e80941Smrg % else: 62b8e80941Smrg PFN_${e.name} ${e.name}; 63b8e80941Smrg % endif 64b8e80941Smrg % endfor 65b8e80941Smrg }; 66b8e80941Smrg }; 67b8e80941Smrg}; 68b8e80941Smrg 69b8e80941Smrg% for e in entrypoints: 70b8e80941Smrg % if e.alias: 71b8e80941Smrg <% continue %> 72b8e80941Smrg % endif 73b8e80941Smrg % if e.guard is not None: 74b8e80941Smrg#ifdef ${e.guard} 75b8e80941Smrg % endif 76b8e80941Smrg % for layer in LAYERS: 77b8e80941Smrg ${e.return_type} ${e.prefixed_name(layer)}(${e.decl_params()}); 78b8e80941Smrg % endfor 79b8e80941Smrg % if e.guard is not None: 80b8e80941Smrg#endif // ${e.guard} 81b8e80941Smrg % endif 82b8e80941Smrg% endfor 83b8e80941Smrg""", output_encoding='utf-8') 84b8e80941Smrg 85b8e80941SmrgTEMPLATE_C = Template(u"""\ 86b8e80941Smrg/* 87b8e80941Smrg * Copyright © 2015 Intel Corporation 88b8e80941Smrg * 89b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a 90b8e80941Smrg * copy of this software and associated documentation files (the "Software"), 91b8e80941Smrg * to deal in the Software without restriction, including without limitation 92b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 93b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the 94b8e80941Smrg * Software is furnished to do so, subject to the following conditions: 95b8e80941Smrg * 96b8e80941Smrg * The above copyright notice and this permission notice (including the next 97b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the 98b8e80941Smrg * Software. 99b8e80941Smrg * 100b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 101b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 102b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 103b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 104b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 105b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 106b8e80941Smrg * IN THE SOFTWARE. 107b8e80941Smrg */ 108b8e80941Smrg 109b8e80941Smrg/* This file generated from ${filename}, don't edit directly. */ 110b8e80941Smrg 111b8e80941Smrg#include "tu_private.h" 112b8e80941Smrg 113b8e80941Smrgstruct string_map_entry { 114b8e80941Smrg uint32_t name; 115b8e80941Smrg uint32_t hash; 116b8e80941Smrg uint32_t num; 117b8e80941Smrg}; 118b8e80941Smrg 119b8e80941Smrg/* We use a big string constant to avoid lots of relocations from the entry 120b8e80941Smrg * point table to lots of little strings. The entries in the entry point table 121b8e80941Smrg * store the index into this big string. 122b8e80941Smrg */ 123b8e80941Smrg 124b8e80941Smrgstatic const char strings[] = 125b8e80941Smrg% for s in strmap.sorted_strings: 126b8e80941Smrg "${s.string}\\0" 127b8e80941Smrg% endfor 128b8e80941Smrg; 129b8e80941Smrg 130b8e80941Smrgstatic const struct string_map_entry string_map_entries[] = { 131b8e80941Smrg% for s in strmap.sorted_strings: 132b8e80941Smrg { ${s.offset}, ${'{:0=#8x}'.format(s.hash)}, ${s.num} }, /* ${s.string} */ 133b8e80941Smrg% endfor 134b8e80941Smrg}; 135b8e80941Smrg 136b8e80941Smrg/* Hash table stats: 137b8e80941Smrg * size ${len(strmap.sorted_strings)} entries 138b8e80941Smrg * collisions entries: 139b8e80941Smrg% for i in range(10): 140b8e80941Smrg * ${i}${'+' if i == 9 else ' '} ${strmap.collisions[i]} 141b8e80941Smrg% endfor 142b8e80941Smrg */ 143b8e80941Smrg 144b8e80941Smrg#define none 0xffff 145b8e80941Smrgstatic const uint16_t string_map[${strmap.hash_size}] = { 146b8e80941Smrg% for e in strmap.mapping: 147b8e80941Smrg ${ '{:0=#6x}'.format(e) if e >= 0 else 'none' }, 148b8e80941Smrg% endfor 149b8e80941Smrg}; 150b8e80941Smrg 151b8e80941Smrg/* Weak aliases for all potential implementations. These will resolve to 152b8e80941Smrg * NULL if they're not defined, which lets the resolve_entrypoint() function 153b8e80941Smrg * either pick the correct entry point. 154b8e80941Smrg */ 155b8e80941Smrg 156b8e80941Smrg% for layer in LAYERS: 157b8e80941Smrg % for e in entrypoints: 158b8e80941Smrg % if e.alias: 159b8e80941Smrg <% continue %> 160b8e80941Smrg % endif 161b8e80941Smrg % if e.guard is not None: 162b8e80941Smrg#ifdef ${e.guard} 163b8e80941Smrg % endif 164b8e80941Smrg ${e.return_type} ${e.prefixed_name(layer)}(${e.decl_params()}) __attribute__ ((weak)); 165b8e80941Smrg % if e.guard is not None: 166b8e80941Smrg#endif // ${e.guard} 167b8e80941Smrg % endif 168b8e80941Smrg % endfor 169b8e80941Smrg 170b8e80941Smrg const struct tu_dispatch_table ${layer}_layer = { 171b8e80941Smrg % for e in entrypoints: 172b8e80941Smrg % if e.guard is not None: 173b8e80941Smrg#ifdef ${e.guard} 174b8e80941Smrg % endif 175b8e80941Smrg .${e.name} = ${e.prefixed_name(layer)}, 176b8e80941Smrg % if e.guard is not None: 177b8e80941Smrg#endif // ${e.guard} 178b8e80941Smrg % endif 179b8e80941Smrg % endfor 180b8e80941Smrg }; 181b8e80941Smrg% endfor 182b8e80941Smrg 183b8e80941Smrgstatic void * __attribute__ ((noinline)) 184b8e80941Smrgtu_resolve_entrypoint(uint32_t index) 185b8e80941Smrg{ 186b8e80941Smrg return tu_layer.entrypoints[index]; 187b8e80941Smrg} 188b8e80941Smrg 189b8e80941Smrg/** Return true if the core version or extension in which the given entrypoint 190b8e80941Smrg * is defined is enabled. 191b8e80941Smrg * 192b8e80941Smrg * If instance is NULL, we only allow the 3 commands explicitly allowed by the vk 193b8e80941Smrg * spec. 194b8e80941Smrg * 195b8e80941Smrg * If device is NULL, all device extensions are considered enabled. 196b8e80941Smrg */ 197b8e80941Smrgstatic bool 198b8e80941Smrgtu_entrypoint_is_enabled(int index, uint32_t core_version, 199b8e80941Smrg const struct tu_instance_extension_table *instance, 200b8e80941Smrg const struct tu_device_extension_table *device) 201b8e80941Smrg{ 202b8e80941Smrg switch (index) { 203b8e80941Smrg% for e in entrypoints: 204b8e80941Smrg case ${e.num}: 205b8e80941Smrg % if not e.device_command: 206b8e80941Smrg if (device) return false; 207b8e80941Smrg % endif 208b8e80941Smrg % if e.name == 'vkCreateInstance' or e.name == 'vkEnumerateInstanceExtensionProperties' or e.name == 'vkEnumerateInstanceLayerProperties' or e.name == 'vkEnumerateInstanceVersion': 209b8e80941Smrg return !device; 210b8e80941Smrg % elif e.core_version: 211b8e80941Smrg return instance && ${e.core_version.c_vk_version()} <= core_version; 212b8e80941Smrg % elif e.extensions: 213b8e80941Smrg % for ext in e.extensions: 214b8e80941Smrg % if ext.type == 'instance': 215b8e80941Smrg if (instance && instance->${ext.name[3:]}) return true; 216b8e80941Smrg % else: 217b8e80941Smrg if (instance && (!device || device->${ext.name[3:]})) return true; 218b8e80941Smrg % endif 219b8e80941Smrg %endfor 220b8e80941Smrg return false; 221b8e80941Smrg % else: 222b8e80941Smrg return instance; 223b8e80941Smrg % endif 224b8e80941Smrg% endfor 225b8e80941Smrg default: 226b8e80941Smrg return false; 227b8e80941Smrg } 228b8e80941Smrg} 229b8e80941Smrg 230b8e80941Smrgstatic int 231b8e80941Smrgtu_lookup_entrypoint(const char *name) 232b8e80941Smrg{ 233b8e80941Smrg static const uint32_t prime_factor = ${strmap.prime_factor}; 234b8e80941Smrg static const uint32_t prime_step = ${strmap.prime_step}; 235b8e80941Smrg const struct string_map_entry *e; 236b8e80941Smrg uint32_t hash, h; 237b8e80941Smrg uint16_t i; 238b8e80941Smrg const char *p; 239b8e80941Smrg 240b8e80941Smrg hash = 0; 241b8e80941Smrg for (p = name; *p; p++) 242b8e80941Smrg hash = hash * prime_factor + *p; 243b8e80941Smrg 244b8e80941Smrg h = hash; 245b8e80941Smrg while (1) { 246b8e80941Smrg i = string_map[h & ${strmap.hash_mask}]; 247b8e80941Smrg if (i == none) 248b8e80941Smrg return -1; 249b8e80941Smrg e = &string_map_entries[i]; 250b8e80941Smrg if (e->hash == hash && strcmp(name, strings + e->name) == 0) 251b8e80941Smrg return e->num; 252b8e80941Smrg h += prime_step; 253b8e80941Smrg } 254b8e80941Smrg 255b8e80941Smrg return -1; 256b8e80941Smrg} 257b8e80941Smrg 258b8e80941Smrgvoid * 259b8e80941Smrgtu_lookup_entrypoint_unchecked(const char *name) 260b8e80941Smrg{ 261b8e80941Smrg int index = tu_lookup_entrypoint(name); 262b8e80941Smrg if (index < 0) 263b8e80941Smrg return NULL; 264b8e80941Smrg return tu_resolve_entrypoint(index); 265b8e80941Smrg} 266b8e80941Smrg 267b8e80941Smrgvoid * 268b8e80941Smrgtu_lookup_entrypoint_checked(const char *name, 269b8e80941Smrg uint32_t core_version, 270b8e80941Smrg const struct tu_instance_extension_table *instance, 271b8e80941Smrg const struct tu_device_extension_table *device) 272b8e80941Smrg{ 273b8e80941Smrg int index = tu_lookup_entrypoint(name); 274b8e80941Smrg if (index < 0 || !tu_entrypoint_is_enabled(index, core_version, instance, device)) 275b8e80941Smrg return NULL; 276b8e80941Smrg return tu_resolve_entrypoint(index); 277b8e80941Smrg}""", output_encoding='utf-8') 278b8e80941Smrg 279b8e80941SmrgU32_MASK = 2**32 - 1 280b8e80941Smrg 281b8e80941SmrgPRIME_FACTOR = 5024183 282b8e80941SmrgPRIME_STEP = 19 283b8e80941Smrg 284b8e80941Smrgdef round_to_pow2(x): 285b8e80941Smrg return 2**int(math.ceil(math.log(x, 2))) 286b8e80941Smrg 287b8e80941Smrgclass StringIntMapEntry(object): 288b8e80941Smrg def __init__(self, string, num): 289b8e80941Smrg self.string = string 290b8e80941Smrg self.num = num 291b8e80941Smrg 292b8e80941Smrg # Calculate the same hash value that we will calculate in C. 293b8e80941Smrg h = 0 294b8e80941Smrg for c in string: 295b8e80941Smrg h = ((h * PRIME_FACTOR) + ord(c)) & U32_MASK 296b8e80941Smrg self.hash = h 297b8e80941Smrg 298b8e80941Smrg self.offset = None 299b8e80941Smrg 300b8e80941Smrgclass StringIntMap(object): 301b8e80941Smrg def __init__(self): 302b8e80941Smrg self.baked = False 303b8e80941Smrg self.strings = dict() 304b8e80941Smrg 305b8e80941Smrg def add_string(self, string, num): 306b8e80941Smrg assert not self.baked 307b8e80941Smrg assert string not in self.strings 308b8e80941Smrg assert num >= 0 and num < 2**31 309b8e80941Smrg self.strings[string] = StringIntMapEntry(string, num) 310b8e80941Smrg 311b8e80941Smrg def bake(self): 312b8e80941Smrg self.sorted_strings = \ 313b8e80941Smrg sorted(self.strings.values(), key=lambda x: x.string) 314b8e80941Smrg offset = 0 315b8e80941Smrg for entry in self.sorted_strings: 316b8e80941Smrg entry.offset = offset 317b8e80941Smrg offset += len(entry.string) + 1 318b8e80941Smrg 319b8e80941Smrg # Save off some values that we'll need in C 320b8e80941Smrg self.hash_size = round_to_pow2(len(self.strings) * 1.25) 321b8e80941Smrg self.hash_mask = self.hash_size - 1 322b8e80941Smrg self.prime_factor = PRIME_FACTOR 323b8e80941Smrg self.prime_step = PRIME_STEP 324b8e80941Smrg 325b8e80941Smrg self.mapping = [-1] * self.hash_size 326b8e80941Smrg self.collisions = [0] * 10 327b8e80941Smrg for idx, s in enumerate(self.sorted_strings): 328b8e80941Smrg level = 0 329b8e80941Smrg h = s.hash 330b8e80941Smrg while self.mapping[h & self.hash_mask] >= 0: 331b8e80941Smrg h = h + PRIME_STEP 332b8e80941Smrg level = level + 1 333b8e80941Smrg self.collisions[min(level, 9)] += 1 334b8e80941Smrg self.mapping[h & self.hash_mask] = idx 335b8e80941Smrg 336b8e80941SmrgEntrypointParam = namedtuple('EntrypointParam', 'type name decl') 337b8e80941Smrg 338b8e80941Smrgclass EntrypointBase(object): 339b8e80941Smrg def __init__(self, name): 340b8e80941Smrg self.name = name 341b8e80941Smrg self.alias = None 342b8e80941Smrg self.guard = None 343b8e80941Smrg self.enabled = False 344b8e80941Smrg self.num = None 345b8e80941Smrg # Extensions which require this entrypoint 346b8e80941Smrg self.core_version = None 347b8e80941Smrg self.extensions = [] 348b8e80941Smrg 349b8e80941Smrgclass Entrypoint(EntrypointBase): 350b8e80941Smrg def __init__(self, name, return_type, params, guard = None): 351b8e80941Smrg super(Entrypoint, self).__init__(name) 352b8e80941Smrg self.return_type = return_type 353b8e80941Smrg self.params = params 354b8e80941Smrg self.guard = guard 355b8e80941Smrg self.device_command = len(params) > 0 and (params[0].type == 'VkDevice' or params[0].type == 'VkQueue' or params[0].type == 'VkCommandBuffer') 356b8e80941Smrg 357b8e80941Smrg def prefixed_name(self, prefix): 358b8e80941Smrg assert self.name.startswith('vk') 359b8e80941Smrg return prefix + '_' + self.name[2:] 360b8e80941Smrg 361b8e80941Smrg def decl_params(self): 362b8e80941Smrg return ', '.join(p.decl for p in self.params) 363b8e80941Smrg 364b8e80941Smrg def call_params(self): 365b8e80941Smrg return ', '.join(p.name for p in self.params) 366b8e80941Smrg 367b8e80941Smrgclass EntrypointAlias(EntrypointBase): 368b8e80941Smrg def __init__(self, name, entrypoint): 369b8e80941Smrg super(EntrypointAlias, self).__init__(name) 370b8e80941Smrg self.alias = entrypoint 371b8e80941Smrg self.device_command = entrypoint.device_command 372b8e80941Smrg 373b8e80941Smrg def prefixed_name(self, prefix): 374b8e80941Smrg return self.alias.prefixed_name(prefix) 375b8e80941Smrg 376b8e80941Smrgdef get_entrypoints(doc, entrypoints_to_defines, start_index): 377b8e80941Smrg """Extract the entry points from the registry.""" 378b8e80941Smrg entrypoints = OrderedDict() 379b8e80941Smrg 380b8e80941Smrg for command in doc.findall('./commands/command'): 381b8e80941Smrg if 'alias' in command.attrib: 382b8e80941Smrg alias = command.attrib['name'] 383b8e80941Smrg target = command.attrib['alias'] 384b8e80941Smrg entrypoints[alias] = EntrypointAlias(alias, entrypoints[target]) 385b8e80941Smrg else: 386b8e80941Smrg name = command.find('./proto/name').text 387b8e80941Smrg ret_type = command.find('./proto/type').text 388b8e80941Smrg params = [EntrypointParam( 389b8e80941Smrg type = p.find('./type').text, 390b8e80941Smrg name = p.find('./name').text, 391b8e80941Smrg decl = ''.join(p.itertext()) 392b8e80941Smrg ) for p in command.findall('./param')] 393b8e80941Smrg guard = entrypoints_to_defines.get(name) 394b8e80941Smrg # They really need to be unique 395b8e80941Smrg assert name not in entrypoints 396b8e80941Smrg entrypoints[name] = Entrypoint(name, ret_type, params, guard) 397b8e80941Smrg 398b8e80941Smrg for feature in doc.findall('./feature'): 399b8e80941Smrg assert feature.attrib['api'] == 'vulkan' 400b8e80941Smrg version = VkVersion(feature.attrib['number']) 401b8e80941Smrg if version > MAX_API_VERSION: 402b8e80941Smrg continue 403b8e80941Smrg 404b8e80941Smrg for command in feature.findall('./require/command'): 405b8e80941Smrg e = entrypoints[command.attrib['name']] 406b8e80941Smrg e.enabled = True 407b8e80941Smrg assert e.core_version is None 408b8e80941Smrg e.core_version = version 409b8e80941Smrg 410b8e80941Smrg supported_exts = dict((ext.name, ext) for ext in EXTENSIONS) 411b8e80941Smrg for extension in doc.findall('.extensions/extension'): 412b8e80941Smrg ext_name = extension.attrib['name'] 413b8e80941Smrg if ext_name not in supported_exts: 414b8e80941Smrg continue 415b8e80941Smrg 416b8e80941Smrg ext = supported_exts[ext_name] 417b8e80941Smrg ext.type = extension.attrib['type'] 418b8e80941Smrg 419b8e80941Smrg for command in extension.findall('./require/command'): 420b8e80941Smrg e = entrypoints[command.attrib['name']] 421b8e80941Smrg e.enabled = True 422b8e80941Smrg assert e.core_version is None 423b8e80941Smrg e.extensions.append(ext) 424b8e80941Smrg 425b8e80941Smrg # if the base command is not supported by the driver yet, don't alias aliases 426b8e80941Smrg for e in entrypoints.values(): 427b8e80941Smrg if e.alias and not e.alias.enabled: 428b8e80941Smrg e_clone = copy.deepcopy(e.alias) 429b8e80941Smrg e_clone.enabled = True 430b8e80941Smrg e_clone.name = e.name 431b8e80941Smrg entrypoints[e.name] = e_clone 432b8e80941Smrg 433b8e80941Smrg return [e for e in entrypoints.values() if e.enabled] 434b8e80941Smrg 435b8e80941Smrg 436b8e80941Smrgdef get_entrypoints_defines(doc): 437b8e80941Smrg """Maps entry points to extension defines.""" 438b8e80941Smrg entrypoints_to_defines = {} 439b8e80941Smrg 440b8e80941Smrg for extension in doc.findall('./extensions/extension[@protect]'): 441b8e80941Smrg define = extension.attrib['protect'] 442b8e80941Smrg 443b8e80941Smrg for entrypoint in extension.findall('./require/command'): 444b8e80941Smrg fullname = entrypoint.attrib['name'] 445b8e80941Smrg entrypoints_to_defines[fullname] = define 446b8e80941Smrg 447b8e80941Smrg platform_define = {} 448b8e80941Smrg for platform in doc.findall('./platforms/platform'): 449b8e80941Smrg name = platform.attrib['name'] 450b8e80941Smrg define = platform.attrib['protect'] 451b8e80941Smrg platform_define[name] = define 452b8e80941Smrg 453b8e80941Smrg for extension in doc.findall('./extensions/extension[@platform]'): 454b8e80941Smrg platform = extension.attrib['platform'] 455b8e80941Smrg define = platform_define[platform] 456b8e80941Smrg 457b8e80941Smrg for entrypoint in extension.findall('./require/command'): 458b8e80941Smrg fullname = entrypoint.attrib['name'] 459b8e80941Smrg entrypoints_to_defines[fullname] = define 460b8e80941Smrg 461b8e80941Smrg return entrypoints_to_defines 462b8e80941Smrg 463b8e80941Smrg 464b8e80941Smrgdef gen_code(entrypoints): 465b8e80941Smrg """Generate the C code.""" 466b8e80941Smrg strmap = StringIntMap() 467b8e80941Smrg for e in entrypoints: 468b8e80941Smrg strmap.add_string(e.name, e.num) 469b8e80941Smrg strmap.bake() 470b8e80941Smrg 471b8e80941Smrg return TEMPLATE_C.render(entrypoints=entrypoints, 472b8e80941Smrg LAYERS=LAYERS, 473b8e80941Smrg strmap=strmap, 474b8e80941Smrg filename=os.path.basename(__file__)) 475b8e80941Smrg 476b8e80941Smrg 477b8e80941Smrgdef main(): 478b8e80941Smrg parser = argparse.ArgumentParser() 479b8e80941Smrg parser.add_argument('--outdir', help='Where to write the files.', 480b8e80941Smrg required=True) 481b8e80941Smrg parser.add_argument('--xml', 482b8e80941Smrg help='Vulkan API XML file.', 483b8e80941Smrg required=True, 484b8e80941Smrg action='append', 485b8e80941Smrg dest='xml_files') 486b8e80941Smrg args = parser.parse_args() 487b8e80941Smrg 488b8e80941Smrg entrypoints = [] 489b8e80941Smrg 490b8e80941Smrg for filename in args.xml_files: 491b8e80941Smrg doc = et.parse(filename) 492b8e80941Smrg entrypoints += get_entrypoints(doc, get_entrypoints_defines(doc), 493b8e80941Smrg start_index=len(entrypoints)) 494b8e80941Smrg 495b8e80941Smrg for num, e in enumerate(entrypoints): 496b8e80941Smrg e.num = num 497b8e80941Smrg 498b8e80941Smrg # For outputting entrypoints.h we generate a tu_EntryPoint() prototype 499b8e80941Smrg # per entry point. 500b8e80941Smrg with open(os.path.join(args.outdir, 'tu_entrypoints.h'), 'wb') as f: 501b8e80941Smrg f.write(TEMPLATE_H.render(entrypoints=entrypoints, 502b8e80941Smrg LAYERS=LAYERS, 503b8e80941Smrg filename=os.path.basename(__file__))) 504b8e80941Smrg with open(os.path.join(args.outdir, 'tu_entrypoints.c'), 'wb') as f: 505b8e80941Smrg f.write(gen_code(entrypoints)) 506b8e80941Smrg 507b8e80941Smrg 508b8e80941Smrgif __name__ == '__main__': 509b8e80941Smrg main() 510