1COPYRIGHT = """\ 2/* 3 * Copyright 2020 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 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sub license, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial portions 15 * of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 20 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 */ 25""" 26 27import argparse 28import math 29import os 30 31from mako.template import Template 32 33# Mesa-local imports must be declared in meson variable 34# '{file_without_suffix}_depend_files'. 35from vk_entrypoints import get_entrypoints_from_xml 36 37# We generate a static hash table for entry point lookup 38# (vkGetProcAddress). We use a linear congruential generator for our hash 39# function and a power-of-two size table. The prime numbers are determined 40# experimentally. 41 42TEMPLATE_H = Template(COPYRIGHT + """\ 43/* This file generated from ${filename}, don't edit directly. */ 44 45#ifndef VK_DISPATCH_TABLE_H 46#define VK_DISPATCH_TABLE_H 47 48#include "vulkan/vulkan.h" 49#include "vulkan/vk_android_native_buffer.h" 50 51#include "vk_extensions.h" 52 53/* Windows api conflict */ 54#ifdef _WIN32 55#include <windows.h> 56#ifdef CreateSemaphore 57#undef CreateSemaphore 58#endif 59#ifdef CreateEvent 60#undef CreateEvent 61#endif 62#endif 63 64#ifdef __cplusplus 65extern "C" { 66#endif 67 68#ifdef _MSC_VER 69VKAPI_ATTR void VKAPI_CALL vk_entrypoint_stub(void); 70#endif 71 72<%def name="dispatch_table(entrypoints)"> 73% for e in entrypoints: 74 % if e.alias: 75 <% continue %> 76 % endif 77 % if e.guard is not None: 78#ifdef ${e.guard} 79 % endif 80 % if e.aliases: 81 union { 82 PFN_vk${e.name} ${e.name}; 83 % for a in e.aliases: 84 PFN_vk${a.name} ${a.name}; 85 % endfor 86 }; 87 % else: 88 PFN_vk${e.name} ${e.name}; 89 % endif 90 % if e.guard is not None: 91#else 92 % if e.aliases: 93 union { 94 PFN_vkVoidFunction ${e.name}; 95 % for a in e.aliases: 96 PFN_vkVoidFunction ${a.name}; 97 % endfor 98 }; 99 % else: 100 PFN_vkVoidFunction ${e.name}; 101 % endif 102#endif 103 % endif 104% endfor 105</%def> 106 107<%def name="entrypoint_table(type, entrypoints)"> 108struct vk_${type}_entrypoint_table { 109% for e in entrypoints: 110 % if e.guard is not None: 111#ifdef ${e.guard} 112 % endif 113 PFN_vk${e.name} ${e.name}; 114 % if e.guard is not None: 115#else 116 PFN_vkVoidFunction ${e.name}; 117# endif 118 % endif 119% endfor 120}; 121</%def> 122 123struct vk_instance_dispatch_table { 124 ${dispatch_table(instance_entrypoints)} 125}; 126 127struct vk_physical_device_dispatch_table { 128 ${dispatch_table(physical_device_entrypoints)} 129}; 130 131struct vk_device_dispatch_table { 132 ${dispatch_table(device_entrypoints)} 133}; 134 135struct vk_dispatch_table { 136 union { 137 struct { 138 struct vk_instance_dispatch_table instance; 139 struct vk_physical_device_dispatch_table physical_device; 140 struct vk_device_dispatch_table device; 141 }; 142 143 struct { 144 ${dispatch_table(instance_entrypoints)} 145 ${dispatch_table(physical_device_entrypoints)} 146 ${dispatch_table(device_entrypoints)} 147 }; 148 }; 149}; 150 151${entrypoint_table('instance', instance_entrypoints)} 152${entrypoint_table('physical_device', physical_device_entrypoints)} 153${entrypoint_table('device', device_entrypoints)} 154 155<%def name="uncompacted_dispatch_table(entrypoints)"> 156% for e in entrypoints: 157 % if e.alias: 158 <% continue %> 159 % endif 160 % if e.guard is not None: 161#ifdef ${e.guard} 162 % endif 163 PFN_vk${e.name} ${e.name}; 164 % if e.aliases: 165 % for a in e.aliases: 166 PFN_vk${a.name} ${a.name}; 167 % endfor 168 % endif 169 % if e.guard is not None: 170#else 171 PFN_vkVoidFunction ${e.name}; 172 % if e.aliases: 173 % for a in e.aliases: 174 PFN_vkVoidFunction ${a.name}; 175 % endfor 176 % endif 177#endif 178 % endif 179% endfor 180</%def> 181 182 183struct vk_instance_uncompacted_dispatch_table { 184 ${uncompacted_dispatch_table(instance_entrypoints)} 185}; 186 187struct vk_physical_device_uncompacted_dispatch_table { 188 ${uncompacted_dispatch_table(physical_device_entrypoints)} 189}; 190 191struct vk_device_uncompacted_dispatch_table { 192 ${uncompacted_dispatch_table(device_entrypoints)} 193}; 194 195struct vk_uncompacted_dispatch_table { 196 union { 197 struct { 198 struct vk_instance_uncompacted_dispatch_table instance; 199 struct vk_physical_device_uncompacted_dispatch_table physical_device; 200 struct vk_device_uncompacted_dispatch_table device; 201 }; 202 203 struct { 204 ${uncompacted_dispatch_table(instance_entrypoints)} 205 ${uncompacted_dispatch_table(physical_device_entrypoints)} 206 ${uncompacted_dispatch_table(device_entrypoints)} 207 }; 208 }; 209}; 210 211void 212vk_instance_dispatch_table_load(struct vk_instance_dispatch_table *table, 213 PFN_vkGetInstanceProcAddr gpa, 214 VkInstance instance); 215void 216vk_physical_device_dispatch_table_load(struct vk_physical_device_dispatch_table *table, 217 PFN_vkGetInstanceProcAddr gpa, 218 VkInstance instance); 219void 220vk_device_dispatch_table_load(struct vk_device_dispatch_table *table, 221 PFN_vkGetDeviceProcAddr gpa, 222 VkDevice device); 223 224void 225vk_instance_uncompacted_dispatch_table_load(struct vk_instance_uncompacted_dispatch_table *table, 226 PFN_vkGetInstanceProcAddr gpa, 227 VkInstance instance); 228void 229vk_physical_device_uncompacted_dispatch_table_load(struct vk_physical_device_uncompacted_dispatch_table *table, 230 PFN_vkGetInstanceProcAddr gpa, 231 VkInstance instance); 232void 233vk_device_uncompacted_dispatch_table_load(struct vk_device_uncompacted_dispatch_table *table, 234 PFN_vkGetDeviceProcAddr gpa, 235 VkDevice device); 236 237void vk_instance_dispatch_table_from_entrypoints( 238 struct vk_instance_dispatch_table *dispatch_table, 239 const struct vk_instance_entrypoint_table *entrypoint_table, 240 bool overwrite); 241 242void vk_physical_device_dispatch_table_from_entrypoints( 243 struct vk_physical_device_dispatch_table *dispatch_table, 244 const struct vk_physical_device_entrypoint_table *entrypoint_table, 245 bool overwrite); 246 247void vk_device_dispatch_table_from_entrypoints( 248 struct vk_device_dispatch_table *dispatch_table, 249 const struct vk_device_entrypoint_table *entrypoint_table, 250 bool overwrite); 251 252PFN_vkVoidFunction 253vk_instance_dispatch_table_get(const struct vk_instance_dispatch_table *table, 254 const char *name); 255 256PFN_vkVoidFunction 257vk_physical_device_dispatch_table_get(const struct vk_physical_device_dispatch_table *table, 258 const char *name); 259 260PFN_vkVoidFunction 261vk_device_dispatch_table_get(const struct vk_device_dispatch_table *table, 262 const char *name); 263 264PFN_vkVoidFunction 265vk_instance_dispatch_table_get_if_supported( 266 const struct vk_instance_dispatch_table *table, 267 const char *name, 268 uint32_t core_version, 269 const struct vk_instance_extension_table *instance_exts); 270 271PFN_vkVoidFunction 272vk_physical_device_dispatch_table_get_if_supported( 273 const struct vk_physical_device_dispatch_table *table, 274 const char *name, 275 uint32_t core_version, 276 const struct vk_instance_extension_table *instance_exts); 277 278PFN_vkVoidFunction 279vk_device_dispatch_table_get_if_supported( 280 const struct vk_device_dispatch_table *table, 281 const char *name, 282 uint32_t core_version, 283 const struct vk_instance_extension_table *instance_exts, 284 const struct vk_device_extension_table *device_exts); 285 286#ifdef __cplusplus 287} 288#endif 289 290#endif /* VK_DISPATCH_TABLE_H */ 291""") 292 293TEMPLATE_C = Template(COPYRIGHT + """\ 294/* This file generated from ${filename}, don't edit directly. */ 295 296#include "vk_dispatch_table.h" 297 298#include "util/macros.h" 299#include "string.h" 300 301<%def name="load_dispatch_table(type, VkType, ProcAddr, entrypoints)"> 302void 303vk_${type}_dispatch_table_load(struct vk_${type}_dispatch_table *table, 304 PFN_vk${ProcAddr} gpa, 305 ${VkType} obj) 306{ 307% if type != 'physical_device': 308 table->${ProcAddr} = gpa; 309% endif 310% for e in entrypoints: 311 % if e.alias or e.name == '${ProcAddr}': 312 <% continue %> 313 % endif 314 % if e.guard is not None: 315#ifdef ${e.guard} 316 % endif 317 table->${e.name} = (PFN_vk${e.name}) gpa(obj, "vk${e.name}"); 318 % for a in e.aliases: 319 if (table->${e.name} == NULL) { 320 table->${e.name} = (PFN_vk${e.name}) gpa(obj, "vk${a.name}"); 321 } 322 % endfor 323 % if e.guard is not None: 324#endif 325 % endif 326% endfor 327} 328</%def> 329 330${load_dispatch_table('instance', 'VkInstance', 'GetInstanceProcAddr', 331 instance_entrypoints)} 332 333${load_dispatch_table('physical_device', 'VkInstance', 'GetInstanceProcAddr', 334 physical_device_entrypoints)} 335 336${load_dispatch_table('device', 'VkDevice', 'GetDeviceProcAddr', 337 device_entrypoints)} 338 339<%def name="load_uncompacted_dispatch_table(type, VkType, ProcAddr, entrypoints)"> 340void 341vk_${type}_uncompacted_dispatch_table_load(struct vk_${type}_uncompacted_dispatch_table *table, 342 PFN_vk${ProcAddr} gpa, 343 ${VkType} obj) 344{ 345% if type != 'physical_device': 346 table->${ProcAddr} = gpa; 347% endif 348% for e in entrypoints: 349 % if e.alias or e.name == '${ProcAddr}': 350 <% continue %> 351 % endif 352 % if e.guard is not None: 353#ifdef ${e.guard} 354 % endif 355 table->${e.name} = (PFN_vk${e.name}) gpa(obj, "vk${e.name}"); 356 % for a in e.aliases: 357 table->${a.name} = (PFN_vk${a.name}) gpa(obj, "vk${a.name}"); 358 if (table->${e.name} && !table->${a.name}) 359 table->${a.name} = (PFN_vk${a.name}) table->${e.name}; 360 if (!table->${e.name}) 361 table->${e.name} = (PFN_vk${e.name}) table->${a.name}; 362 % endfor 363 % if e.guard is not None: 364#endif 365 % endif 366% endfor 367} 368</%def> 369 370${load_uncompacted_dispatch_table('instance', 'VkInstance', 'GetInstanceProcAddr', 371 instance_entrypoints)} 372 373${load_uncompacted_dispatch_table('physical_device', 'VkInstance', 'GetInstanceProcAddr', 374 physical_device_entrypoints)} 375 376${load_uncompacted_dispatch_table('device', 'VkDevice', 'GetDeviceProcAddr', 377 device_entrypoints)} 378 379 380struct string_map_entry { 381 uint32_t name; 382 uint32_t hash; 383 uint32_t num; 384}; 385 386/* We use a big string constant to avoid lots of reloctions from the entry 387 * point table to lots of little strings. The entries in the entry point table 388 * store the index into this big string. 389 */ 390 391<%def name="strmap(strmap, prefix)"> 392static const char ${prefix}_strings[] = 393% for s in strmap.sorted_strings: 394 "${s.string}\\0" 395% endfor 396; 397 398static const struct string_map_entry ${prefix}_string_map_entries[] = { 399% for s in strmap.sorted_strings: 400 { ${s.offset}, ${'{:0=#8x}'.format(s.hash)}, ${s.num} }, /* ${s.string} */ 401% endfor 402}; 403 404/* Hash table stats: 405 * size ${len(strmap.sorted_strings)} entries 406 * collisions entries: 407% for i in range(10): 408 * ${i}${'+' if i == 9 else ' '} ${strmap.collisions[i]} 409% endfor 410 */ 411 412#define none 0xffff 413static const uint16_t ${prefix}_string_map[${strmap.hash_size}] = { 414% for e in strmap.mapping: 415 ${ '{:0=#6x}'.format(e) if e >= 0 else 'none' }, 416% endfor 417}; 418 419static int 420${prefix}_string_map_lookup(const char *str) 421{ 422 static const uint32_t prime_factor = ${strmap.prime_factor}; 423 static const uint32_t prime_step = ${strmap.prime_step}; 424 const struct string_map_entry *e; 425 uint32_t hash, h; 426 uint16_t i; 427 const char *p; 428 429 hash = 0; 430 for (p = str; *p; p++) 431 hash = hash * prime_factor + *p; 432 433 h = hash; 434 while (1) { 435 i = ${prefix}_string_map[h & ${strmap.hash_mask}]; 436 if (i == none) 437 return -1; 438 e = &${prefix}_string_map_entries[i]; 439 if (e->hash == hash && strcmp(str, ${prefix}_strings + e->name) == 0) 440 return e->num; 441 h += prime_step; 442 } 443 444 return -1; 445} 446</%def> 447 448${strmap(instance_strmap, 'instance')} 449${strmap(physical_device_strmap, 'physical_device')} 450${strmap(device_strmap, 'device')} 451 452<% assert len(instance_entrypoints) < 2**8 %> 453static const uint8_t instance_compaction_table[] = { 454% for e in instance_entrypoints: 455 ${e.disp_table_index}, 456% endfor 457}; 458 459<% assert len(physical_device_entrypoints) < 2**8 %> 460static const uint8_t physical_device_compaction_table[] = { 461% for e in physical_device_entrypoints: 462 ${e.disp_table_index}, 463% endfor 464}; 465 466<% assert len(device_entrypoints) < 2**16 %> 467static const uint16_t device_compaction_table[] = { 468% for e in device_entrypoints: 469 ${e.disp_table_index}, 470% endfor 471}; 472 473static bool 474vk_instance_entrypoint_is_enabled(int index, uint32_t core_version, 475 const struct vk_instance_extension_table *instance) 476{ 477 switch (index) { 478% for e in instance_entrypoints: 479 case ${e.entry_table_index}: 480 /* ${e.name} */ 481 % if e.core_version: 482 return ${e.core_version.c_vk_version()} <= core_version; 483 % elif e.extensions: 484 % for ext in e.extensions: 485 % if ext.type == 'instance': 486 if (instance->${ext.name[3:]}) return true; 487 % else: 488 /* All device extensions are considered enabled at the instance level */ 489 return true; 490 % endif 491 % endfor 492 return false; 493 % else: 494 return true; 495 % endif 496% endfor 497 default: 498 return false; 499 } 500} 501 502/** Return true if the core version or extension in which the given entrypoint 503 * is defined is enabled. 504 * 505 * If device is NULL, all device extensions are considered enabled. 506 */ 507static bool 508vk_physical_device_entrypoint_is_enabled(int index, uint32_t core_version, 509 const struct vk_instance_extension_table *instance) 510{ 511 switch (index) { 512% for e in physical_device_entrypoints: 513 case ${e.entry_table_index}: 514 /* ${e.name} */ 515 % if e.core_version: 516 return ${e.core_version.c_vk_version()} <= core_version; 517 % elif e.extensions: 518 % for ext in e.extensions: 519 % if ext.type == 'instance': 520 if (instance->${ext.name[3:]}) return true; 521 % else: 522 /* All device extensions are considered enabled at the instance level */ 523 return true; 524 % endif 525 % endfor 526 return false; 527 % else: 528 return true; 529 % endif 530% endfor 531 default: 532 return false; 533 } 534} 535 536/** Return true if the core version or extension in which the given entrypoint 537 * is defined is enabled. 538 * 539 * If device is NULL, all device extensions are considered enabled. 540 */ 541static bool 542vk_device_entrypoint_is_enabled(int index, uint32_t core_version, 543 const struct vk_instance_extension_table *instance, 544 const struct vk_device_extension_table *device) 545{ 546 switch (index) { 547% for e in device_entrypoints: 548 case ${e.entry_table_index}: 549 /* ${e.name} */ 550 % if e.core_version: 551 return ${e.core_version.c_vk_version()} <= core_version; 552 % elif e.extensions: 553 % for ext in e.extensions: 554 % if ext.type == 'instance': 555 if (instance->${ext.name[3:]}) return true; 556 % else: 557 if (!device || device->${ext.name[3:]}) return true; 558 % endif 559 % endfor 560 return false; 561 % else: 562 return true; 563 % endif 564% endfor 565 default: 566 return false; 567 } 568} 569 570#ifdef _MSC_VER 571VKAPI_ATTR void VKAPI_CALL vk_entrypoint_stub(void) 572{ 573 unreachable("Entrypoint not implemented"); 574} 575 576static const void *get_function_target(const void *func) 577{ 578 const uint8_t *address = func; 579#ifdef _M_X64 580 /* Incremental linking may indirect through relative jump */ 581 if (*address == 0xE9) 582 { 583 /* Compute JMP target if the first byte is opcode 0xE9 */ 584 uint32_t offset; 585 memcpy(&offset, address + 1, 4); 586 address += offset + 5; 587 } 588#else 589 /* Add other platforms here if necessary */ 590#endif 591 return address; 592} 593 594static bool vk_function_is_stub(PFN_vkVoidFunction func) 595{ 596 return (func == vk_entrypoint_stub) || (get_function_target(func) == get_function_target(vk_entrypoint_stub)); 597} 598#endif 599 600<%def name="dispatch_table_from_entrypoints(type)"> 601void vk_${type}_dispatch_table_from_entrypoints( 602 struct vk_${type}_dispatch_table *dispatch_table, 603 const struct vk_${type}_entrypoint_table *entrypoint_table, 604 bool overwrite) 605{ 606 PFN_vkVoidFunction *disp = (PFN_vkVoidFunction *)dispatch_table; 607 PFN_vkVoidFunction *entry = (PFN_vkVoidFunction *)entrypoint_table; 608 609 if (overwrite) { 610 memset(dispatch_table, 0, sizeof(*dispatch_table)); 611 for (unsigned i = 0; i < ARRAY_SIZE(${type}_compaction_table); i++) { 612#ifdef _MSC_VER 613 assert(entry[i] != NULL); 614 if (vk_function_is_stub(entry[i])) 615#else 616 if (entry[i] == NULL) 617#endif 618 continue; 619 unsigned disp_index = ${type}_compaction_table[i]; 620 assert(disp[disp_index] == NULL); 621 disp[disp_index] = entry[i]; 622 } 623 } else { 624 for (unsigned i = 0; i < ARRAY_SIZE(${type}_compaction_table); i++) { 625 unsigned disp_index = ${type}_compaction_table[i]; 626#ifdef _MSC_VER 627 assert(entry[i] != NULL); 628 if (disp[disp_index] == NULL && !vk_function_is_stub(entry[i])) 629#else 630 if (disp[disp_index] == NULL) 631#endif 632 disp[disp_index] = entry[i]; 633 } 634 } 635} 636</%def> 637 638${dispatch_table_from_entrypoints('instance')} 639${dispatch_table_from_entrypoints('physical_device')} 640${dispatch_table_from_entrypoints('device')} 641 642<%def name="lookup_funcs(type)"> 643static PFN_vkVoidFunction 644vk_${type}_dispatch_table_get_for_entry_index( 645 const struct vk_${type}_dispatch_table *table, int entry_index) 646{ 647 assert(entry_index < ARRAY_SIZE(${type}_compaction_table)); 648 int disp_index = ${type}_compaction_table[entry_index]; 649 return ((PFN_vkVoidFunction *)table)[disp_index]; 650} 651 652PFN_vkVoidFunction 653vk_${type}_dispatch_table_get( 654 const struct vk_${type}_dispatch_table *table, const char *name) 655{ 656 int entry_index = ${type}_string_map_lookup(name); 657 if (entry_index < 0) 658 return NULL; 659 660 return vk_${type}_dispatch_table_get_for_entry_index(table, entry_index); 661} 662</%def> 663 664${lookup_funcs('instance')} 665${lookup_funcs('physical_device')} 666${lookup_funcs('device')} 667 668PFN_vkVoidFunction 669vk_instance_dispatch_table_get_if_supported( 670 const struct vk_instance_dispatch_table *table, 671 const char *name, 672 uint32_t core_version, 673 const struct vk_instance_extension_table *instance_exts) 674{ 675 int entry_index = instance_string_map_lookup(name); 676 if (entry_index < 0) 677 return NULL; 678 679 if (!vk_instance_entrypoint_is_enabled(entry_index, core_version, 680 instance_exts)) 681 return NULL; 682 683 return vk_instance_dispatch_table_get_for_entry_index(table, entry_index); 684} 685 686PFN_vkVoidFunction 687vk_physical_device_dispatch_table_get_if_supported( 688 const struct vk_physical_device_dispatch_table *table, 689 const char *name, 690 uint32_t core_version, 691 const struct vk_instance_extension_table *instance_exts) 692{ 693 int entry_index = physical_device_string_map_lookup(name); 694 if (entry_index < 0) 695 return NULL; 696 697 if (!vk_physical_device_entrypoint_is_enabled(entry_index, core_version, 698 instance_exts)) 699 return NULL; 700 701 return vk_physical_device_dispatch_table_get_for_entry_index(table, entry_index); 702} 703 704PFN_vkVoidFunction 705vk_device_dispatch_table_get_if_supported( 706 const struct vk_device_dispatch_table *table, 707 const char *name, 708 uint32_t core_version, 709 const struct vk_instance_extension_table *instance_exts, 710 const struct vk_device_extension_table *device_exts) 711{ 712 int entry_index = device_string_map_lookup(name); 713 if (entry_index < 0) 714 return NULL; 715 716 if (!vk_device_entrypoint_is_enabled(entry_index, core_version, 717 instance_exts, device_exts)) 718 return NULL; 719 720 return vk_device_dispatch_table_get_for_entry_index(table, entry_index); 721} 722""") 723 724U32_MASK = 2**32 - 1 725 726PRIME_FACTOR = 5024183 727PRIME_STEP = 19 728 729class StringIntMapEntry: 730 def __init__(self, string, num): 731 self.string = string 732 self.num = num 733 734 # Calculate the same hash value that we will calculate in C. 735 h = 0 736 for c in string: 737 h = ((h * PRIME_FACTOR) + ord(c)) & U32_MASK 738 self.hash = h 739 740 self.offset = None 741 742def round_to_pow2(x): 743 return 2**int(math.ceil(math.log(x, 2))) 744 745class StringIntMap: 746 def __init__(self): 747 self.baked = False 748 self.strings = {} 749 750 def add_string(self, string, num): 751 assert not self.baked 752 assert string not in self.strings 753 assert 0 <= num < 2**31 754 self.strings[string] = StringIntMapEntry(string, num) 755 756 def bake(self): 757 self.sorted_strings = \ 758 sorted(self.strings.values(), key=lambda x: x.string) 759 offset = 0 760 for entry in self.sorted_strings: 761 entry.offset = offset 762 offset += len(entry.string) + 1 763 764 # Save off some values that we'll need in C 765 self.hash_size = round_to_pow2(len(self.strings) * 1.25) 766 self.hash_mask = self.hash_size - 1 767 self.prime_factor = PRIME_FACTOR 768 self.prime_step = PRIME_STEP 769 770 self.mapping = [-1] * self.hash_size 771 self.collisions = [0] * 10 772 for idx, s in enumerate(self.sorted_strings): 773 level = 0 774 h = s.hash 775 while self.mapping[h & self.hash_mask] >= 0: 776 h = h + PRIME_STEP 777 level = level + 1 778 self.collisions[min(level, 9)] += 1 779 self.mapping[h & self.hash_mask] = idx 780 781def main(): 782 parser = argparse.ArgumentParser() 783 parser.add_argument('--out-c', help='Output C file.') 784 parser.add_argument('--out-h', help='Output H file.') 785 parser.add_argument('--beta', required=True, help='Enable beta extensions.') 786 parser.add_argument('--xml', 787 help='Vulkan API XML file.', 788 required=True, 789 action='append', 790 dest='xml_files') 791 args = parser.parse_args() 792 793 entrypoints = get_entrypoints_from_xml(args.xml_files, args.beta) 794 795 device_entrypoints = [] 796 physical_device_entrypoints = [] 797 instance_entrypoints = [] 798 for e in entrypoints: 799 if e.is_device_entrypoint(): 800 device_entrypoints.append(e) 801 elif e.is_physical_device_entrypoint(): 802 physical_device_entrypoints.append(e) 803 else: 804 instance_entrypoints.append(e) 805 806 for i, e in enumerate(e for e in device_entrypoints if not e.alias): 807 e.disp_table_index = i 808 809 device_strmap = StringIntMap() 810 for i, e in enumerate(device_entrypoints): 811 e.entry_table_index = i 812 device_strmap.add_string("vk" + e.name, e.entry_table_index) 813 device_strmap.bake() 814 815 for i, e in enumerate(e for e in physical_device_entrypoints if not e.alias): 816 e.disp_table_index = i 817 818 physical_device_strmap = StringIntMap() 819 for i, e in enumerate(physical_device_entrypoints): 820 e.entry_table_index = i 821 physical_device_strmap.add_string("vk" + e.name, e.entry_table_index) 822 physical_device_strmap.bake() 823 824 for i, e in enumerate(e for e in instance_entrypoints if not e.alias): 825 e.disp_table_index = i 826 827 instance_strmap = StringIntMap() 828 for i, e in enumerate(instance_entrypoints): 829 e.entry_table_index = i 830 instance_strmap.add_string("vk" + e.name, e.entry_table_index) 831 instance_strmap.bake() 832 833 # For outputting entrypoints.h we generate a anv_EntryPoint() prototype 834 # per entry point. 835 try: 836 if args.out_h: 837 with open(args.out_h, 'w', encoding='utf-8') as f: 838 f.write(TEMPLATE_H.render(instance_entrypoints=instance_entrypoints, 839 physical_device_entrypoints=physical_device_entrypoints, 840 device_entrypoints=device_entrypoints, 841 filename=os.path.basename(__file__))) 842 if args.out_c: 843 with open(args.out_c, 'w', encoding='utf-8') as f: 844 f.write(TEMPLATE_C.render(instance_entrypoints=instance_entrypoints, 845 physical_device_entrypoints=physical_device_entrypoints, 846 device_entrypoints=device_entrypoints, 847 instance_strmap=instance_strmap, 848 physical_device_strmap=physical_device_strmap, 849 device_strmap=device_strmap, 850 filename=os.path.basename(__file__))) 851 except Exception: 852 # In the event there's an error, this imports some helpers from mako 853 # to print a useful stack trace and prints it, then exits with 854 # status 1, if python is run with debug; otherwise it just raises 855 # the exception 856 import sys 857 from mako import exceptions 858 print(exceptions.text_error_template().render(), file=sys.stderr) 859 sys.exit(1) 860 861 862if __name__ == '__main__': 863 main() 864