1# coding=utf-8 2# 3# Copyright © 2015, 2017 Intel Corporation 4# 5# Permission is hereby granted, free of charge, to any person obtaining a 6# copy of this software and associated documentation files (the "Software"), 7# to deal in the Software without restriction, including without limitation 8# the rights to use, copy, modify, merge, publish, distribute, sublicense, 9# and/or sell copies of the Software, and to permit persons to whom the 10# Software is furnished to do so, subject to the following conditions: 11# 12# The above copyright notice and this permission notice (including the next 13# paragraph) shall be included in all copies or substantial portions of the 14# Software. 15# 16# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22# IN THE SOFTWARE. 23# 24 25import argparse 26import functools 27import math 28import os 29import xml.etree.ElementTree as et 30 31from collections import OrderedDict, namedtuple 32from mako.template import Template 33 34from lvp_extensions import * 35 36# We generate a static hash table for entry point lookup 37# (vkGetProcAddress). We use a linear congruential generator for our hash 38# function and a power-of-two size table. The prime numbers are determined 39# experimentally. 40 41# We currently don't use layers in lvp, but keeping the ability for anv 42# anyways, so we can use it for device groups. 43LAYERS = [ 44 'lvp' 45] 46 47TEMPLATE_H = Template("""\ 48/* This file generated from ${filename}, don't edit directly. */ 49 50struct lvp_instance_dispatch_table { 51 union { 52 void *entrypoints[${len(instance_entrypoints)}]; 53 struct { 54 % for e in instance_entrypoints: 55 % if e.guard is not None: 56#ifdef ${e.guard} 57 PFN_${e.name} ${e.name}; 58#else 59 void *${e.name}; 60# endif 61 % else: 62 PFN_${e.name} ${e.name}; 63 % endif 64 % endfor 65 }; 66 }; 67}; 68 69struct lvp_physical_device_dispatch_table { 70 union { 71 void *entrypoints[${len(physical_device_entrypoints)}]; 72 struct { 73 % for e in physical_device_entrypoints: 74 % if e.guard is not None: 75#ifdef ${e.guard} 76 PFN_${e.name} ${e.name}; 77#else 78 void *${e.name}; 79# endif 80 % else: 81 PFN_${e.name} ${e.name}; 82 % endif 83 % endfor 84 }; 85 }; 86}; 87 88struct lvp_device_dispatch_table { 89 union { 90 void *entrypoints[${len(device_entrypoints)}]; 91 struct { 92 % for e in device_entrypoints: 93 % if e.guard is not None: 94#ifdef ${e.guard} 95 PFN_${e.name} ${e.name}; 96#else 97 void *${e.name}; 98# endif 99 % else: 100 PFN_${e.name} ${e.name}; 101 % endif 102 % endfor 103 }; 104 }; 105}; 106 107extern const struct lvp_instance_dispatch_table lvp_instance_dispatch_table; 108%for layer in LAYERS: 109extern const struct lvp_physical_device_dispatch_table ${layer}_physical_device_dispatch_table; 110%endfor 111%for layer in LAYERS: 112extern const struct lvp_device_dispatch_table ${layer}_device_dispatch_table; 113%endfor 114 115% for e in instance_entrypoints: 116 % if e.alias and e.alias.enabled: 117 <% continue %> 118 % endif 119 % if e.guard is not None: 120#ifdef ${e.guard} 121 % endif 122 ${e.return_type} ${e.prefixed_name('lvp')}(${e.decl_params()}); 123 % if e.guard is not None: 124#endif // ${e.guard} 125 % endif 126% endfor 127 128% for e in physical_device_entrypoints: 129 % if e.alias: 130 <% continue %> 131 % endif 132 % if e.guard is not None: 133#ifdef ${e.guard} 134 % endif 135 % for layer in LAYERS: 136 ${e.return_type} ${e.prefixed_name(layer)}(${e.decl_params()}); 137 % endfor 138 % if e.guard is not None: 139#endif // ${e.guard} 140 % endif 141% endfor 142 143% for e in device_entrypoints: 144 % if e.alias and e.alias.enabled: 145 <% continue %> 146 % endif 147 % if e.guard is not None: 148#ifdef ${e.guard} 149 % endif 150 % for layer in LAYERS: 151 ${e.return_type} ${e.prefixed_name(layer)}(${e.decl_params()}); 152 % endfor 153 % if e.guard is not None: 154#endif // ${e.guard} 155 % endif 156% endfor 157""", output_encoding='utf-8') 158 159TEMPLATE_C = Template(u"""\ 160/* 161 * Copyright © 2015 Intel Corporation 162 * 163 * Permission is hereby granted, free of charge, to any person obtaining a 164 * copy of this software and associated documentation files (the "Software"), 165 * to deal in the Software without restriction, including without limitation 166 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 167 * and/or sell copies of the Software, and to permit persons to whom the 168 * Software is furnished to do so, subject to the following conditions: 169 * 170 * The above copyright notice and this permission notice (including the next 171 * paragraph) shall be included in all copies or substantial portions of the 172 * Software. 173 * 174 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 175 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 176 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 177 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 178 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 179 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 180 * IN THE SOFTWARE. 181 */ 182 183/* This file generated from ${filename}, don't edit directly. */ 184 185#include "lvp_private.h" 186 187#include "util/macros.h" 188struct string_map_entry { 189 uint32_t name; 190 uint32_t hash; 191 uint32_t num; 192}; 193 194/* We use a big string constant to avoid lots of relocations from the entry 195 * point table to lots of little strings. The entries in the entry point table 196 * store the index into this big string. 197 */ 198 199<%def name="strmap(strmap, prefix)"> 200static const char ${prefix}_strings[] = 201% for s in strmap.sorted_strings: 202 "${s.string}\\0" 203% endfor 204; 205 206static const struct string_map_entry ${prefix}_string_map_entries[] = { 207% for s in strmap.sorted_strings: 208 { ${s.offset}, ${'{:0=#8x}'.format(s.hash)}, ${s.num} }, /* ${s.string} */ 209% endfor 210}; 211 212/* Hash table stats: 213 * size ${len(strmap.sorted_strings)} entries 214 * collisions entries: 215% for i in range(10): 216 * ${i}${'+' if i == 9 else ' '} ${strmap.collisions[i]} 217% endfor 218 */ 219 220#define none 0xffff 221static const uint16_t ${prefix}_string_map[${strmap.hash_size}] = { 222% for e in strmap.mapping: 223 ${ '{:0=#6x}'.format(e) if e >= 0 else 'none' }, 224% endfor 225}; 226 227static int 228${prefix}_string_map_lookup(const char *str) 229{ 230 static const uint32_t prime_factor = ${strmap.prime_factor}; 231 static const uint32_t prime_step = ${strmap.prime_step}; 232 const struct string_map_entry *e; 233 uint32_t hash, h; 234 uint16_t i; 235 const char *p; 236 237 hash = 0; 238 for (p = str; *p; p++) 239 hash = hash * prime_factor + *p; 240 241 h = hash; 242 while (1) { 243 i = ${prefix}_string_map[h & ${strmap.hash_mask}]; 244 if (i == none) 245 return -1; 246 e = &${prefix}_string_map_entries[i]; 247 if (e->hash == hash && strcmp(str, ${prefix}_strings + e->name) == 0) 248 return e->num; 249 h += prime_step; 250 } 251 252 return -1; 253} 254 255static const char * 256${prefix}_entry_name(int num) 257{ 258 for (int i = 0; i < ARRAY_SIZE(${prefix}_string_map_entries); i++) { 259 if (${prefix}_string_map_entries[i].num == num) 260 return &${prefix}_strings[${prefix}_string_map_entries[i].name]; 261 } 262 return NULL; 263} 264</%def> 265 266${strmap(instance_strmap, 'instance')} 267${strmap(physical_device_strmap, 'physical_device')} 268${strmap(device_strmap, 'device')} 269 270/* Weak aliases for all potential implementations. These will resolve to 271 * NULL if they're not defined, which lets the resolve_entrypoint() function 272 * either pick the correct entry point. 273 */ 274 275% for e in instance_entrypoints: 276 % if e.alias and e.alias.enabled: 277 <% continue %> 278 % endif 279 % if e.guard is not None: 280#ifdef ${e.guard} 281 % endif 282 ${e.return_type} ${e.prefixed_name('lvp')}(${e.decl_params()}) __attribute__ ((weak)); 283 % if e.guard is not None: 284#endif // ${e.guard} 285 % endif 286% endfor 287 288const struct lvp_instance_dispatch_table lvp_instance_dispatch_table = { 289% for e in instance_entrypoints: 290 % if e.guard is not None: 291#ifdef ${e.guard} 292 % endif 293 .${e.name} = ${e.prefixed_name('lvp')}, 294 % if e.guard is not None: 295#endif // ${e.guard} 296 % endif 297% endfor 298}; 299 300% for e in physical_device_entrypoints: 301 % if e.alias and e.alias.enabled: 302 <% continue %> 303 % endif 304 % if e.guard is not None: 305#ifdef ${e.guard} 306 % endif 307 ${e.return_type} ${e.prefixed_name('lvp')}(${e.decl_params()}) __attribute__ ((weak)); 308 % if e.guard is not None: 309#endif // ${e.guard} 310 % endif 311% endfor 312 313const struct lvp_physical_device_dispatch_table lvp_physical_device_dispatch_table = { 314% for e in physical_device_entrypoints: 315 % if e.guard is not None: 316#ifdef ${e.guard} 317 % endif 318 .${e.name} = ${e.prefixed_name('lvp')}, 319 % if e.guard is not None: 320#endif // ${e.guard} 321 % endif 322% endfor 323}; 324 325 326% for layer in LAYERS: 327 % for e in device_entrypoints: 328 % if e.alias and e.alias.enabled: 329 <% continue %> 330 % endif 331 % if e.guard is not None: 332#ifdef ${e.guard} 333 % endif 334 % if layer == 'lvp': 335 ${e.return_type} __attribute__ ((weak)) 336 ${e.prefixed_name('lvp')}(${e.decl_params()}) 337 { 338 % if e.params[0].type == 'VkDevice': 339 LVP_FROM_HANDLE(lvp_device, lvp_device, ${e.params[0].name}); 340 return lvp_device->dispatch.${e.name}(${e.call_params()}); 341 % elif e.params[0].type == 'VkCommandBuffer': 342 LVP_FROM_HANDLE(lvp_cmd_buffer, lvp_cmd_buffer, ${e.params[0].name}); 343 return lvp_cmd_buffer->device->dispatch.${e.name}(${e.call_params()}); 344 % elif e.params[0].type == 'VkQueue': 345 LVP_FROM_HANDLE(lvp_queue, lvp_queue, ${e.params[0].name}); 346 return lvp_queue->device->dispatch.${e.name}(${e.call_params()}); 347 % else: 348 assert(!"Unhandled device child trampoline case: ${e.params[0].type}"); 349 % endif 350 } 351 % else: 352 ${e.return_type} ${e.prefixed_name(layer)}(${e.decl_params()}) __attribute__ ((weak)); 353 % endif 354 % if e.guard is not None: 355#endif // ${e.guard} 356 % endif 357 % endfor 358 359 const struct lvp_device_dispatch_table ${layer}_device_dispatch_table = { 360 % for e in device_entrypoints: 361 % if e.guard is not None: 362#ifdef ${e.guard} 363 % endif 364 .${e.name} = ${e.prefixed_name(layer)}, 365 % if e.guard is not None: 366#endif // ${e.guard} 367 % endif 368 % endfor 369 }; 370% endfor 371 372 373/** Return true if the core version or extension in which the given entrypoint 374 * is defined is enabled. 375 * 376 * If device is NULL, all device extensions are considered enabled. 377 */ 378bool 379lvp_instance_entrypoint_is_enabled(int index, uint32_t core_version, 380 const struct lvp_instance_extension_table *instance) 381{ 382 switch (index) { 383% for e in instance_entrypoints: 384 case ${e.num}: 385 /* ${e.name} */ 386 % if e.core_version: 387 return ${e.core_version.c_vk_version()} <= core_version; 388 % elif e.extensions: 389 % for ext in e.extensions: 390 % if ext.type == 'instance': 391 if (instance->${ext.name[3:]}) return true; 392 % else: 393 /* All device extensions are considered enabled at the instance level */ 394 return true; 395 % endif 396 % endfor 397 return false; 398 % else: 399 return true; 400 % endif 401% endfor 402 default: 403 return false; 404 } 405} 406 407/** Return true if the core version or extension in which the given entrypoint 408 * is defined is enabled. 409 * 410 * If device is NULL, all device extensions are considered enabled. 411 */ 412bool 413lvp_physical_device_entrypoint_is_enabled(int index, uint32_t core_version, 414 const struct lvp_instance_extension_table *instance) 415{ 416 switch (index) { 417% for e in physical_device_entrypoints: 418 case ${e.num}: 419 /* ${e.name} */ 420 % if e.core_version: 421 return ${e.core_version.c_vk_version()} <= core_version; 422 % elif e.extensions: 423 % for ext in e.extensions: 424 % if ext.type == 'instance': 425 if (instance->${ext.name[3:]}) return true; 426 % else: 427 /* All device extensions are considered enabled at the instance level */ 428 return true; 429 % endif 430 % endfor 431 return false; 432 % else: 433 return true; 434 % endif 435% endfor 436 default: 437 return false; 438 } 439} 440 441/** Return true if the core version or extension in which the given entrypoint 442 * is defined is enabled. 443 * 444 * If device is NULL, all device extensions are considered enabled. 445 */ 446bool 447lvp_device_entrypoint_is_enabled(int index, uint32_t core_version, 448 const struct lvp_instance_extension_table *instance, 449 const struct lvp_device_extension_table *device) 450{ 451 switch (index) { 452% for e in device_entrypoints: 453 case ${e.num}: 454 /* ${e.name} */ 455 % if e.core_version: 456 return ${e.core_version.c_vk_version()} <= core_version; 457 % elif e.extensions: 458 % for ext in e.extensions: 459 % if ext.type == 'instance': 460 <% assert False %> 461 % else: 462 if (!device || device->${ext.name[3:]}) return true; 463 % endif 464 % endfor 465 return false; 466 % else: 467 return true; 468 % endif 469% endfor 470 default: 471 return false; 472 } 473} 474 475int 476lvp_get_instance_entrypoint_index(const char *name) 477{ 478 return instance_string_map_lookup(name); 479} 480 481int 482lvp_get_physical_device_entrypoint_index(const char *name) 483{ 484 return physical_device_string_map_lookup(name); 485} 486 487int 488lvp_get_device_entrypoint_index(const char *name) 489{ 490 return device_string_map_lookup(name); 491} 492 493const char * 494lvp_get_instance_entry_name(int index) 495{ 496 return instance_entry_name(index); 497} 498 499const char * 500lvp_get_physical_device_entry_name(int index) 501{ 502 return physical_device_entry_name(index); 503} 504 505const char * 506lvp_get_device_entry_name(int index) 507{ 508 return device_entry_name(index); 509} 510 511static void * __attribute__ ((noinline)) 512lvp_resolve_device_entrypoint(uint32_t index) 513{ 514 return lvp_device_dispatch_table.entrypoints[index]; 515} 516 517void * 518lvp_lookup_entrypoint(const char *name) 519{ 520 int idx = lvp_get_instance_entrypoint_index(name); 521 if (idx >= 0) 522 return lvp_instance_dispatch_table.entrypoints[idx]; 523 524 idx = lvp_get_physical_device_entrypoint_index(name); 525 if (idx >= 0) 526 return lvp_physical_device_dispatch_table.entrypoints[idx]; 527 528 idx = lvp_get_device_entrypoint_index(name); 529 if (idx >= 0) 530 return lvp_resolve_device_entrypoint(idx); 531 532 return NULL; 533}""", output_encoding='utf-8') 534 535U32_MASK = 2**32 - 1 536 537PRIME_FACTOR = 5024183 538PRIME_STEP = 19 539 540def round_to_pow2(x): 541 return 2**int(math.ceil(math.log(x, 2))) 542 543class StringIntMapEntry(object): 544 def __init__(self, string, num): 545 self.string = string 546 self.num = num 547 548 # Calculate the same hash value that we will calculate in C. 549 h = 0 550 for c in string: 551 h = ((h * PRIME_FACTOR) + ord(c)) & U32_MASK 552 self.hash = h 553 554 self.offset = None 555 556class StringIntMap(object): 557 def __init__(self): 558 self.baked = False 559 self.strings = dict() 560 561 def add_string(self, string, num): 562 assert not self.baked 563 assert string not in self.strings 564 assert num >= 0 and num < 2**31 565 self.strings[string] = StringIntMapEntry(string, num) 566 567 def bake(self): 568 self.sorted_strings = \ 569 sorted(self.strings.values(), key=lambda x: x.string) 570 offset = 0 571 for entry in self.sorted_strings: 572 entry.offset = offset 573 offset += len(entry.string) + 1 574 575 # Save off some values that we'll need in C 576 self.hash_size = round_to_pow2(len(self.strings) * 1.25) 577 self.hash_mask = self.hash_size - 1 578 self.prime_factor = PRIME_FACTOR 579 self.prime_step = PRIME_STEP 580 581 self.mapping = [-1] * self.hash_size 582 self.collisions = [0] * 10 583 for idx, s in enumerate(self.sorted_strings): 584 level = 0 585 h = s.hash 586 while self.mapping[h & self.hash_mask] >= 0: 587 h = h + PRIME_STEP 588 level = level + 1 589 self.collisions[min(level, 9)] += 1 590 self.mapping[h & self.hash_mask] = idx 591 592EntrypointParam = namedtuple('EntrypointParam', 'type name decl') 593 594class EntrypointBase(object): 595 def __init__(self, name): 596 self.name = name 597 self.alias = None 598 self.guard = None 599 self.enabled = False 600 self.num = None 601 # Extensions which require this entrypoint 602 self.core_version = None 603 self.extensions = [] 604 605 def prefixed_name(self, prefix): 606 assert self.name.startswith('vk') 607 return prefix + '_' + self.name[2:] 608 609class Entrypoint(EntrypointBase): 610 def __init__(self, name, return_type, params, guard = None): 611 super(Entrypoint, self).__init__(name) 612 self.return_type = return_type 613 self.params = params 614 self.guard = guard 615 616 def is_physical_device_entrypoint(self): 617 return self.params[0].type in ('VkPhysicalDevice', ) 618 619 def is_device_entrypoint(self): 620 return self.params[0].type in ('VkDevice', 'VkCommandBuffer', 'VkQueue') 621 622 def decl_params(self): 623 return ', '.join(p.decl for p in self.params) 624 625 def call_params(self): 626 return ', '.join(p.name for p in self.params) 627 628class EntrypointAlias(EntrypointBase): 629 def __init__(self, name, entrypoint): 630 super(EntrypointAlias, self).__init__(name) 631 self.alias = entrypoint 632 633 def is_physical_device_entrypoint(self): 634 return self.alias.is_physical_device_entrypoint() 635 636 def is_device_entrypoint(self): 637 return self.alias.is_device_entrypoint() 638 639 def prefixed_name(self, prefix): 640 if self.alias.enabled: 641 return self.alias.prefixed_name(prefix) 642 return super(EntrypointAlias, self).prefixed_name(prefix) 643 644 @property 645 def params(self): 646 return self.alias.params 647 648 @property 649 def return_type(self): 650 return self.alias.return_type 651 652 def decl_params(self): 653 return self.alias.decl_params() 654 655 def call_params(self): 656 return self.alias.call_params() 657 658def get_entrypoints(doc, entrypoints_to_defines): 659 """Extract the entry points from the registry.""" 660 entrypoints = OrderedDict() 661 662 for command in doc.findall('./commands/command'): 663 if 'alias' in command.attrib: 664 alias = command.attrib['name'] 665 target = command.attrib['alias'] 666 entrypoints[alias] = EntrypointAlias(alias, entrypoints[target]) 667 else: 668 name = command.find('./proto/name').text 669 ret_type = command.find('./proto/type').text 670 params = [EntrypointParam( 671 type = p.find('./type').text, 672 name = p.find('./name').text, 673 decl = ''.join(p.itertext()) 674 ) for p in command.findall('./param')] 675 guard = entrypoints_to_defines.get(name) 676 # They really need to be unique 677 assert name not in entrypoints 678 entrypoints[name] = Entrypoint(name, ret_type, params, guard) 679 680 for feature in doc.findall('./feature'): 681 assert feature.attrib['api'] == 'vulkan' 682 version = VkVersion(feature.attrib['number']) 683 if version > MAX_API_VERSION: 684 continue 685 686 for command in feature.findall('./require/command'): 687 e = entrypoints[command.attrib['name']] 688 e.enabled = True 689 assert e.core_version is None 690 e.core_version = version 691 692 supported_exts = dict((ext.name, ext) for ext in EXTENSIONS) 693 for extension in doc.findall('.extensions/extension'): 694 ext_name = extension.attrib['name'] 695 if ext_name not in supported_exts: 696 continue 697 698 ext = supported_exts[ext_name] 699 ext.type = extension.attrib['type'] 700 701 for command in extension.findall('./require/command'): 702 e = entrypoints[command.attrib['name']] 703 e.enabled = True 704 assert e.core_version is None 705 e.extensions.append(ext) 706 707 # if the base command is not supported by the driver yet, don't alias aliases 708 for e in entrypoints.values(): 709 if e.alias and not e.alias.enabled: 710 e_clone = copy.deepcopy(e.alias) 711 e_clone.enabled = True 712 e_clone.name = e.name 713 entrypoints[e.name] = e_clone 714 715 return [e for e in entrypoints.values() if e.enabled] 716 717 718def get_entrypoints_defines(doc): 719 """Maps entry points to extension defines.""" 720 entrypoints_to_defines = {} 721 722 platform_define = {} 723 for platform in doc.findall('./platforms/platform'): 724 name = platform.attrib['name'] 725 define = platform.attrib['protect'] 726 platform_define[name] = define 727 728 for extension in doc.findall('./extensions/extension[@platform]'): 729 platform = extension.attrib['platform'] 730 define = platform_define[platform] 731 732 for entrypoint in extension.findall('./require/command'): 733 fullname = entrypoint.attrib['name'] 734 entrypoints_to_defines[fullname] = define 735 736 return entrypoints_to_defines 737 738def main(): 739 parser = argparse.ArgumentParser() 740 parser.add_argument('--outdir', help='Where to write the files.', 741 required=True) 742 parser.add_argument('--xml', 743 help='Vulkan API XML file.', 744 required=True, 745 action='append', 746 dest='xml_files') 747 args = parser.parse_args() 748 749 entrypoints = [] 750 751 for filename in args.xml_files: 752 doc = et.parse(filename) 753 entrypoints += get_entrypoints(doc, get_entrypoints_defines(doc)) 754 755 device_entrypoints = [] 756 physical_device_entrypoints = [] 757 instance_entrypoints = [] 758 for e in entrypoints: 759 if e.is_device_entrypoint(): 760 device_entrypoints.append(e) 761 elif e.is_physical_device_entrypoint(): 762 physical_device_entrypoints.append(e) 763 else: 764 instance_entrypoints.append(e) 765 766 device_strmap = StringIntMap() 767 for num, e in enumerate(device_entrypoints): 768 device_strmap.add_string(e.name, num) 769 e.num = num 770 device_strmap.bake() 771 772 physical_device_strmap = StringIntMap() 773 for num, e in enumerate(physical_device_entrypoints): 774 physical_device_strmap.add_string(e.name, num) 775 e.num = num 776 physical_device_strmap.bake() 777 778 instance_strmap = StringIntMap() 779 for num, e in enumerate(instance_entrypoints): 780 instance_strmap.add_string(e.name, num) 781 e.num = num 782 instance_strmap.bake() 783 784 # For outputting entrypoints.h we generate a lvp_EntryPoint() prototype 785 # per entry point. 786 try: 787 with open(os.path.join(args.outdir, 'lvp_entrypoints.h'), 'wb') as f: 788 f.write(TEMPLATE_H.render(instance_entrypoints=instance_entrypoints, 789 physical_device_entrypoints=physical_device_entrypoints, 790 device_entrypoints=device_entrypoints, 791 LAYERS=LAYERS, 792 filename=os.path.basename(__file__))) 793 with open(os.path.join(args.outdir, 'lvp_entrypoints.c'), 'wb') as f: 794 f.write(TEMPLATE_C.render(instance_entrypoints=instance_entrypoints, 795 physical_device_entrypoints=physical_device_entrypoints, 796 device_entrypoints=device_entrypoints, 797 LAYERS=LAYERS, 798 instance_strmap=instance_strmap, 799 physical_device_strmap=physical_device_strmap, 800 device_strmap=device_strmap, 801 filename=os.path.basename(__file__))) 802 except Exception: 803 # In the event there's an error, this imports some helpers from mako 804 # to print a useful stack trace and prints it, then exits with 805 # status 1, if python is run with debug; otherwise it just raises 806 # the exception 807 if __debug__: 808 import sys 809 from mako import exceptions 810 sys.stderr.write(exceptions.text_error_template().render() + '\n') 811 sys.exit(1) 812 raise 813 814 815if __name__ == '__main__': 816 main() 817