1#!/usr/bin/env vpython 2# 3# [VPYTHON:BEGIN] 4# wheel: < 5# name: "infra/python/wheels/perfect-hash-py2_py3" 6# version: "version:0.2.1" 7# > 8# [VPYTHON:END] 9# 10# Copyright 2018 The ANGLE Project Authors. All rights reserved. 11# Use of this source code is governed by a BSD-style license that can be 12# found in the LICENSE file. 13# 14# gen_builtin_symbols.py: 15# Code generation for the built-in symbol tables. 16 17from collections import OrderedDict 18from datetime import date 19from perfect_hash import generate_hash, Hash2 20import argparse 21import hashlib 22import json 23import re 24import os 25import sys 26import random 27 28template_immutablestring_cpp = """// GENERATED FILE - DO NOT EDIT. 29// Generated by {script_name} using data from {variable_data_source_name} and 30// {function_data_source_name}. 31// 32// Copyright {copyright_year} The ANGLE Project Authors. All rights reserved. 33// Use of this source code is governed by a BSD-style license that can be 34// found in the LICENSE file. 35// 36// ImmutableString_{source_label}autogen.cpp: Wrapper for static or pool allocated char arrays, that are guaranteed to be 37// valid and unchanged for the duration of the compilation. 38// Implements mangledNameHash using perfect hash function from gen_builtin_symbols.py 39 40#include "compiler/translator/ImmutableString.h" 41 42std::ostream &operator<<(std::ostream &os, const sh::ImmutableString &str) 43{{ 44 return os.write(str.data(), str.length()); 45}} 46 47#if defined(_MSC_VER) 48# pragma warning(disable : 4309) // truncation of constant value 49#endif 50 51 52namespace 53{{ 54 55constexpr int mangledkT1[] = {{{mangled_S1}}}; 56constexpr int mangledkT2[] = {{{mangled_S2}}}; 57constexpr int mangledkG[] = {{{mangled_G}}}; 58 59int MangledHashG(const char *key, const int *T) 60{{ 61 int sum = 0; 62 63 for (int i = 0; key[i] != '\\0'; i++) 64 {{ 65 sum += T[i] * key[i]; 66 sum %= {mangled_NG}; 67 }} 68 return mangledkG[sum]; 69}} 70 71int MangledPerfectHash(const char *key) 72{{ 73 if (strlen(key) > {mangled_NS}) 74 return 0; 75 76 return (MangledHashG(key, mangledkT1) + MangledHashG(key, mangledkT2)) % {mangled_NG}; 77}} 78 79constexpr int unmangledkT1[] = {{{unmangled_S1}}}; 80constexpr int unmangledkT2[] = {{{unmangled_S2}}}; 81constexpr int unmangledkG[] = {{{unmangled_G}}}; 82 83int UnmangledHashG(const char *key, const int *T) 84{{ 85 int sum = 0; 86 87 for (int i = 0; key[i] != '\\0'; i++) 88 {{ 89 sum += T[i] * key[i]; 90 sum %= {unmangled_NG}; 91 }} 92 return unmangledkG[sum]; 93}} 94 95int UnmangledPerfectHash(const char *key) 96{{ 97 if (strlen(key) > {unmangled_NS}) 98 return 0; 99 100 return (UnmangledHashG(key, unmangledkT1) + UnmangledHashG(key, unmangledkT2)) % {unmangled_NG}; 101}} 102 103}} 104 105namespace sh 106{{ 107 108template <> 109const size_t ImmutableString::FowlerNollVoHash<4>::kFnvPrime = 16777619u; 110 111template <> 112const size_t ImmutableString::FowlerNollVoHash<4>::kFnvOffsetBasis = 0x811c9dc5u; 113 114template <> 115const size_t ImmutableString::FowlerNollVoHash<8>::kFnvPrime = 116 static_cast<size_t>(1099511628211ull); 117 118template <> 119const size_t ImmutableString::FowlerNollVoHash<8>::kFnvOffsetBasis = 120 static_cast<size_t>(0xcbf29ce484222325ull); 121 122uint32_t ImmutableString::mangledNameHash() const 123{{ 124 return MangledPerfectHash(data()); 125}} 126 127uint32_t ImmutableString::unmangledNameHash() const 128{{ 129 return UnmangledPerfectHash(data()); 130}} 131 132}} // namespace sh 133""" 134 135template_immutablestringtest_cpp = """// GENERATED FILE - DO NOT EDIT. 136// Generated by {script_name} using data from {function_data_source_name}. 137// 138// Copyright {copyright_year} The ANGLE Project Authors. All rights reserved. 139// Use of this source code is governed by a BSD-style license that can be 140// found in the LICENSE file. 141// 142// ImmutableString_test_{source_label}autogen.cpp: 143// Tests for matching script-generated hashes with runtime computed hashes. 144 145#include "compiler/translator/ImmutableString.h" 146#include "gtest/gtest.h" 147 148namespace sh 149{{ 150 151TEST(ImmutableStringTest, ScriptGeneratedHashesMatch) 152{{ 153{script_generated_hash_tests} 154{unmangled_script_generated_hash_tests} 155}} 156 157}} // namespace sh 158""" 159 160# The header file has a "get" function for each variable. They are used in traversers. 161# It also declares id values of built-ins with human readable names, so they can be used to identify built-ins. 162template_builtin_header = """// GENERATED FILE - DO NOT EDIT. 163// Generated by {script_name} using data from {variable_data_source_name} and 164// {function_data_source_name}. 165// 166// Copyright {copyright_year} The ANGLE Project Authors. All rights reserved. 167// Use of this source code is governed by a BSD-style license that can be 168// found in the LICENSE file. 169// 170// BuiltIn_{header_label}autogen.h: 171// Compile-time initialized built-ins. 172 173#ifndef COMPILER_TRANSLATOR_TREEUTIL_BUILTIN_AUTOGEN_H_ 174#define COMPILER_TRANSLATOR_TREEUTIL_BUILTIN_AUTOGEN_H_ 175 176#include "compiler/translator/SymbolUniqueId.h" 177 178namespace sh 179{{ 180 181class TVariable; 182 183class BuiltInId 184{{ 185public: 186 187{builtin_id_declarations} 188 189}}; // class BuiltInId 190 191namespace BuiltInVariable 192{{ 193 194{get_variable_declarations} 195 196}} // namespace BuiltInVariable 197 198}} // namespace sh 199 200#endif // COMPILER_TRANSLATOR_TREEUTIL_BUILTIN_AUTOGEN_H_ 201""" 202 203template_symboltable_header = """// GENERATED FILE - DO NOT EDIT. 204// Generated by {script_name} using data from {variable_data_source_name} and 205// {function_data_source_name}. 206// 207// Copyright {copyright_year} The ANGLE Project Authors. All rights reserved. 208// Use of this source code is governed by a BSD-style license that can be 209// found in the LICENSE file. 210// 211// SymbolTable_autogen.h: 212// Autogenerated member variables of TSymbolTable. 213 214#ifndef COMPILER_TRANSLATOR_SYMBOLTABLE_AUTOGEN_H_ 215#define COMPILER_TRANSLATOR_SYMBOLTABLE_AUTOGEN_H_ 216 217namespace sh 218{{ 219 220class TSymbolTableBase 221{{ 222 public: 223 TSymbolTableBase() = default; 224{declare_member_variables} 225}}; 226 227}} // namespace sh 228 229#endif // COMPILER_TRANSLATOR_SYMBOLTABLE_AUTOGEN_H_ 230""" 231 232# By having the variables defined in a cpp file we ensure that there's just one instance of each of the declared variables. 233template_symboltable_cpp = """// GENERATED FILE - DO NOT EDIT. 234// Generated by {script_name} using data from {variable_data_source_name} and 235// {function_data_source_name}. 236// 237// Copyright {copyright_year} The ANGLE Project Authors. All rights reserved. 238// Use of this source code is governed by a BSD-style license that can be 239// found in the LICENSE file. 240// 241// SymbolTable_{source_label}autogen.cpp: 242// Compile-time initialized built-ins. 243 244#include "compiler/translator/SymbolTable.h" 245 246#include "angle_gl.h" 247#include "compiler/translator/tree_util/BuiltIn.h" 248#include "compiler/translator/ImmutableString.h" 249#include "compiler/translator/StaticType.h" 250#include "compiler/translator/Symbol.h" 251#include "compiler/translator/SymbolTable.h" 252 253namespace sh 254{{ 255using Resources = ShBuiltInResources; 256using TableBase = TSymbolTableBase; 257 258// Since some of the BuiltInId declarations are used outside of constexpr expressions, we need to 259// have these definitions without an initializer. C++17 should eventually remove the need for this. 260{builtin_id_definitions} 261 262const int TSymbolTable::kLastBuiltInId = {last_builtin_id}; 263 264namespace BuiltInName 265{{ 266 267constexpr const ImmutableString _empty(""); 268{name_declarations} 269 270}} // namespace BuiltInName 271 272// TODO(oetuaho): Would be nice to make this a class instead of a namespace so that we could friend 273// this from TVariable. Now symbol constructors taking an id have to be public even though they're 274// not supposed to be accessible from outside of here. http://anglebug.com/2390 275namespace BuiltInVariable 276{{ 277 278{type_array_sizes_declarations} 279 280{variable_declarations} 281 282{get_variable_definitions} 283 284}} // namespace BuiltInVariable 285 286namespace BuiltInParameters 287{{ 288 289{parameter_declarations} 290 291}} // namespace BuiltInParameters 292 293// TODO(oetuaho): Would be nice to make this a class instead of a namespace so that we could friend 294// this from TFunction. Now symbol constructors taking an id have to be public even though they're 295// not supposed to be accessible from outside of here. http://anglebug.com/2390 296namespace Func 297{{ 298 299{function_declarations} 300 301}} // namespace Func 302 303namespace BuiltInArray 304{{ 305using namespace Func; 306using Rule = SymbolRule; 307 308// Rules used to initialize the mangled name array. 309constexpr SymbolRule kRules[] = {{ 310{mangled_rules} 311}}; 312 313// Flat array of all mangled names. 314constexpr const char *kMangledNames[] = {{ 315{mangled_names_array} 316}}; 317 318// Flat array of offsets from a symbol into the rules table. 319constexpr uint16_t kMangledOffsets[] = {{ 320{mangled_offsets_array} 321}}; 322 323using Ext = TExtension; 324 325// Flat array of all unmangled name identifiers. 326constexpr UnmangledEntry unmangled[] = {{ 327{unmangled_array} 328}}; 329 330}} 331 332void TSymbolTable::initializeBuiltInVariables(sh::GLenum shaderType, 333 ShShaderSpec spec, 334 const ShBuiltInResources &resources) 335{{ 336 const TSourceLoc zeroSourceLoc = {{0, 0, 0, 0}}; 337{init_member_variables} 338}} 339 340namespace 341{{ 342uint16_t GetNextRuleIndex(uint32_t nameHash) 343{{ 344 if (nameHash == {num_mangled_names} - 1) 345 return ArraySize(BuiltInArray::kRules); 346 return BuiltInArray::kMangledOffsets[nameHash + 1]; 347}} 348}} // namespace 349 350const TSymbol *TSymbolTable::findBuiltIn(const ImmutableString &name, 351 int shaderVersion) const 352{{ 353 if (name.length() > {max_mangled_name_length}) 354 return nullptr; 355 356 uint32_t nameHash = name.mangledNameHash(); 357 if (nameHash >= {num_mangled_names}) 358 return nullptr; 359 360 const char *actualName = BuiltInArray::kMangledNames[nameHash]; 361 if (name != actualName) 362 return nullptr; 363 364 uint16_t startIndex = BuiltInArray::kMangledOffsets[nameHash]; 365 uint16_t nextIndex = GetNextRuleIndex(nameHash); 366 367 return FindMangledBuiltIn(mShaderSpec, shaderVersion, mShaderType, mResources, *this, BuiltInArray::kRules, startIndex, nextIndex); 368}} 369 370bool TSymbolTable::isUnmangledBuiltInName(const ImmutableString &name, 371 int shaderVersion, 372 const TExtensionBehavior &extensions) const 373{{ 374 if (name.length() > {max_unmangled_name_length}) 375 return false; 376 377 uint32_t nameHash = name.unmangledNameHash(); 378 if (nameHash >= {num_unmangled_names}) 379 return false; 380 381 return BuiltInArray::unmangled[nameHash].matches(name, mShaderSpec, shaderVersion, mShaderType, extensions); 382}} 383 384}} // namespace sh 385""" 386 387template_parsecontext_header = """// GENERATED FILE - DO NOT EDIT. 388// Generated by {script_name} using data from {variable_data_source_name} and 389// {function_data_source_name}. 390// 391// Copyright {copyright_year} The ANGLE Project Authors. All rights reserved. 392// Use of this source code is governed by a BSD-style license that can be 393// found in the LICENSE file. 394// 395// ParseContext_{header_label}autogen.h: 396// Helpers for built-in related checks. 397 398#ifndef COMPILER_TRANSLATOR_PARSECONTEXT_AUTOGEN_H_ 399#define COMPILER_TRANSLATOR_PARSECONTEXT_AUTOGEN_H_ 400 401namespace sh 402{{ 403 404namespace BuiltInGroup 405{{ 406 407{is_in_group_definitions} 408 409}} // namespace BuiltInGroup 410 411}} // namespace sh 412 413#endif // COMPILER_TRANSLATOR_PARSECONTEXT_AUTOGEN_H_ 414 415""" 416 417template_rule = """Rule::Get<{spec}, {version}, {shaders}, {extension}>({symbol_or_var})""" 418 419basic_types_enumeration = [ 420 'Void', 421 'Float', 422 'Double', 423 'Int', 424 'UInt', 425 'Bool', 426 'AtomicCounter', 427 'YuvCscStandardEXT', 428 'Sampler2D', 429 'Sampler3D', 430 'SamplerCube', 431 'Sampler2DArray', 432 'SamplerExternalOES', 433 'SamplerExternal2DY2YEXT', 434 'Sampler2DRect', 435 'Sampler2DMS', 436 'Sampler2DMSArray', 437 'ISampler2D', 438 'ISampler3D', 439 'ISamplerCube', 440 'ISampler2DArray', 441 'ISampler2DMS', 442 'ISampler2DMSArray', 443 'USampler2D', 444 'USampler3D', 445 'USamplerCube', 446 'USampler2DArray', 447 'USampler2DMS', 448 'USampler2DMSArray', 449 'Sampler2DShadow', 450 'SamplerCubeShadow', 451 'Sampler2DArrayShadow', 452 'Sampler1D', 453 'Sampler1DArray', 454 'Sampler1DArrayShadow', 455 'SamplerBuffer', 456 'SamplerCubeArray', 457 'SamplerCubeArrayShadow', 458 'Sampler1DShadow', 459 'Sampler2DRectShadow', 460 'ISampler1D', 461 'ISampler1DArray', 462 'ISampler2DRect', 463 'ISamplerBuffer', 464 'ISamplerCubeArray', 465 'USampler1D', 466 'USampler1DArray', 467 'USampler2DRect', 468 'USamplerBuffer', 469 'USamplerCubeArray', 470 'SamplerVideoWEBGL', 471 'Image2D', 472 'IImage2D', 473 'UImage2D', 474 'Image3D', 475 'IImage3D', 476 'UImage3D', 477 'Image2DArray', 478 'IImage2DArray', 479 'UImage2DArray', 480 'ImageCube', 481 'IImageCube', 482 'UImageCube', 483 'Image1D', 484 'IImage1D', 485 'UImage1D', 486 'Image1DArray', 487 'IImage1DArray', 488 'UImage1DArray', 489 'Image2DMS', 490 'IImage2DMS', 491 'UImage2DMS', 492 'Image2DMSArray', 493 'IImage2DMSArray', 494 'UImage2DMSArray', 495 'Image2DRect', 496 'IImage2DRect', 497 'UImage2DRect', 498 'ImageCubeArray', 499 'IImageCubeArray', 500 'UImageCubeArray', 501 'ImageRect', 502 'IImageRect', 503 'UImageRect', 504 'ImageBuffer', 505 'IImageBuffer', 506 'UImageBuffer', 507 'SubpassInput', 508 'ISubpassInput', 509 'USubpassInput', 510 'SubpassInputMS', 511 'ISubpassInputMS', 512 'USubpassInputMS', 513] 514 515id_counter = 0 516 517 518def set_working_dir(): 519 script_dir = os.path.dirname(os.path.abspath(__file__)) 520 os.chdir(script_dir) 521 522 523def get_basic_mangled_name(basic): 524 index = basic_types_enumeration.index(basic) 525 if index < 26: 526 return '0' + chr(ord('A') + index) 527 if index < 52: 528 return '0' + chr(ord('a') + index - 26) 529 if index < 78: 530 return '1' + chr(ord('A') + index - 52) 531 return '1' + chr(ord('a') + index - 78) 532 533 534essl_levels = [ 535 'ESSL3_2_BUILTINS', 'ESSL3_1_BUILTINS', 'ESSL3_BUILTINS', 'ESSL1_BUILTINS', 'COMMON_BUILTINS' 536] 537 538glsl_levels = [ 539 'GLSL4_6_BUILTINS', 'GLSL4_5_BUILTINS', 'GLSL4_4_BUILTINS', 'GLSL4_3_BUILTINS', 540 'GLSL4_2_BUILTINS', 'GLSL4_1_BUILTINS', 'GLSL4_BUILTINS', 'GLSL3_3_BUILTINS', 541 'GLSL1_5_BUILTINS', 'GLSL1_4_BUILTINS', 'GLSL1_3_BUILTINS', 'GLSL1_2_BUILTINS', 542 'COMMON_BUILTINS' 543] 544 545 546def get_essl_shader_version_for_level(level): 547 if level == None: 548 return '-1' 549 elif level == 'ESSL3_2_BUILTINS': 550 return '320' 551 elif level == 'ESSL3_1_BUILTINS': 552 return '310' 553 elif level == 'ESSL3_BUILTINS': 554 return '300' 555 elif level == 'ESSL1_BUILTINS': 556 return '100' 557 elif level == 'COMMON_BUILTINS': 558 return '0' 559 else: 560 raise Exception('Unsupported symbol table level') 561 562 563def get_glsl_shader_version_for_level(level): 564 if level == None: 565 return '-1' 566 elif level == 'GLSL1_2_BUILTINS': 567 return '120' 568 elif level == 'GLSL1_3_BUILTINS': 569 return '130' 570 elif level == 'GLSL1_4_BUILTINS': 571 return '140' 572 elif level == 'GLSL1_5_BUILTINS': 573 return '150' 574 elif level == 'GLSL3_3_BUILTINS': 575 return '330' 576 elif level == 'GLSL4_BUILTINS': 577 return '400' 578 elif level == 'GLSL4_1_BUILTINS': 579 return '410' 580 elif level == 'GLSL4_2_BUILTINS': 581 return '420' 582 elif level == 'GLSL4_3_BUILTINS': 583 return '430' 584 elif level == 'GLSL4_4_BUILTINS': 585 return '440' 586 elif level == 'GLSL4_5_BUILTINS': 587 return '450' 588 elif level == 'GLSL4_6_BUILTINS': 589 return '460' 590 elif level == 'COMMON_BUILTINS': 591 return '0' 592 else: 593 raise Exception('Unsupported symbol table level') 594 595 596def get_shader_version_for_level(spec, level): 597 if spec == "ESSL": 598 return get_essl_shader_version_for_level(level) 599 else: 600 return get_glsl_shader_version_for_level(level) 601 602 603class GroupedList: 604 """"Class for storing a list of objects grouped by symbol table level and condition.""" 605 606 def __init__(self, hashfn, num_names): 607 self.objs = OrderedDict() 608 self.max_name_length = 0 609 self.hashfn = hashfn 610 self.num_names = num_names 611 self.rule_offset = 0 612 613 def add_entry(self, essl_level, glsl_level, shader_type, name, symbol, essl_extension, 614 glsl_extension, script_generated_hash_tests): 615 if essl_level and essl_level not in essl_levels: 616 raise Exception('Unexpected essl level: ' + str(essl_level)) 617 if glsl_level and glsl_level not in glsl_levels: 618 raise Exception('Unexpected glsl level: ' + str(glsl_level)) 619 if len(name) > self.max_name_length: 620 self.max_name_length = len(name) 621 622 name_hash = mangledNameHash(name, self.hashfn, script_generated_hash_tests, False) 623 if name_hash not in self.objs: 624 self.objs[name_hash] = OrderedDict() 625 626 self.objs[name_hash]['name'] = name 627 628 if essl_extension == 'UNDEFINED' and glsl_extension == 'UNDEFINED': 629 if essl_level: 630 self.objs[name_hash]['essl_level'] = essl_level 631 if glsl_level: 632 self.objs[name_hash]['glsl_level'] = glsl_level 633 self.objs[name_hash]['symbol'] = symbol 634 self.objs[name_hash]['shader_type'] = shader_type 635 636 if essl_extension != 'UNDEFINED': 637 if ('essl_ext_symbol' in self.objs[name_hash] and 638 self.objs[name_hash]['essl_ext_symbol'] != symbol): 639 # Adding a variable that is part of two ESSL extensions 640 if essl_extension != 'UNDEFINED': 641 self.objs[name_hash]['essl_extension2'] = essl_extension 642 self.objs[name_hash]['essl_ext_level2'] = essl_level 643 self.objs[name_hash]['essl_ext_symbol2'] = symbol 644 self.objs[name_hash]['essl_ext_shader_type2'] = shader_type 645 else: 646 self.objs[name_hash]['essl_extension'] = essl_extension 647 self.objs[name_hash]['essl_ext_level'] = essl_level 648 self.objs[name_hash]['essl_ext_symbol'] = symbol 649 self.objs[name_hash]['essl_ext_shader_type'] = shader_type 650 651 if glsl_extension != 'UNDEFINED': 652 self.objs[name_hash]['glsl_extension'] = glsl_extension 653 self.objs[name_hash]['glsl_ext_level'] = glsl_level 654 self.objs[name_hash]['glsl_ext_symbol'] = symbol 655 self.objs[name_hash]['glsl_ext_shader_type'] = shader_type 656 657 def get_max_name_length(self): 658 return self.max_name_length 659 660 def format_rule(self, rule): 661 return template_rule.format(**rule) 662 663 def format_rules(self, rules): 664 return ", ".join([self.format_rule(rule) for rule in rules]) 665 666 def get_rules(self): 667 return self.rules 668 669 def get_names(self): 670 return self.names 671 672 def get_offsets(self): 673 return self.offsets 674 675 def update_arrays(self): 676 677 def add_rule(rules, spec, level, shaders, extension, symbol): 678 var = ("&TableBase::%s" % symbol) if symbol.startswith("m_gl") else None 679 680 rules.append({ 681 "spec": "Spec::%s" % ("ESSL" if spec == "ESSL" else "GLSL"), 682 "version": get_shader_version_for_level(spec, level), 683 "shaders": "Shader::%s" % ("ALL" if shaders == "NONE" else shaders), 684 "extension": "0" if extension == None else "EXT_INDEX(%s)" % extension, 685 "symbol_or_var": symbol.replace("Func::", "") if var is None else var 686 }) 687 688 self.names = [] 689 self.offsets = [] 690 self.rules = [] 691 for hash_val in range(0, self.num_names): 692 if hash_val in self.objs: 693 data = self.objs[hash_val] 694 695 rules = [] 696 697 if "symbol" in data and "essl_level" in data: 698 add_rule(rules, "ESSL", data['essl_level'], data['shader_type'], None, 699 data["symbol"]) 700 701 if "symbol" in data and "glsl_level" in data: 702 add_rule(rules, "GLSL", data['glsl_level'], data['shader_type'], None, 703 data["symbol"]) 704 705 if "essl_ext_symbol" in data: 706 add_rule(rules, "ESSL", data["essl_ext_level"], data["essl_ext_shader_type"], 707 data["essl_extension"], data["essl_ext_symbol"]) 708 709 if "glsl_ext_symbol" in data: 710 add_rule(rules, "GLSL", data["glsl_ext_level"], data["glsl_ext_shader_type"], 711 data["glsl_extension"], data["glsl_ext_symbol"]) 712 713 if "essl_ext_symbol2" in data: 714 add_rule(rules, "ESSL", data["essl_ext_level2"], data["essl_ext_shader_type2"], 715 data["essl_extension2"], data["essl_ext_symbol2"]) 716 717 name = data['name'] 718 name_underscore = name.replace("(", "_") 719 720 self.names.append('"%s"' % name) 721 self.offsets.append("%d, // %s" % (self.rule_offset, name_underscore)) 722 self.rules.append("%s" % self.format_rules(rules)) 723 724 self.rule_offset += len(rules) 725 726 else: 727 self.names.append('""') 728 self.offsets.append('%d, // Empty' % self.rule_offset) 729 730 731class UnmangledGroupedList: 732 """"Class for storing a list of unmangled objects grouped by symbol table level and condition.""" 733 734 def __init__(self, hashfn, num_names): 735 self.objs = OrderedDict() 736 self.max_name_length = 0 737 self.hashfn = hashfn 738 self.num_names = num_names 739 740 def add_entry(self, essl_level, glsl_level, shader_type, name, essl_ext, glsl_ext, 741 essl_extension, glsl_extension, unmangled_script_generated_hash_tests): 742 if essl_level and essl_level not in essl_levels: 743 raise Exception('Unexpected essl level: ' + str(essl_level)) 744 if glsl_level and glsl_level not in glsl_levels: 745 raise Exception('Unexpected glsl level: ' + str(glsl_level)) 746 if len(name) > self.max_name_length: 747 self.max_name_length = len(name) 748 749 name_hash = mangledNameHash(name, self.hashfn, unmangled_script_generated_hash_tests, True) 750 self.objs[name_hash] = OrderedDict() 751 self.objs[name_hash]['name'] = name 752 self.objs[name_hash]['essl_level'] = essl_level 753 self.objs[name_hash]['glsl_level'] = glsl_level 754 self.objs[name_hash]['shader_type'] = shader_type 755 self.objs[name_hash]['essl_ext'] = essl_ext 756 self.objs[name_hash]['glsl_ext'] = glsl_ext 757 self.objs[name_hash]['essl_extension'] = essl_extension 758 self.objs[name_hash]['glsl_extension'] = glsl_extension 759 760 def has_key(self, essl_level, glsl_level, shader_type, name): 761 name_hash = mangledNameHash(name, self.hashfn, None, True, False) 762 if name_hash not in self.objs: 763 return False 764 entry = self.objs[name_hash] 765 if entry['essl_level'] != essl_level: 766 return False 767 if entry['glsl_level'] != glsl_level: 768 return False 769 if entry['shader_type'] != shader_type: 770 return False 771 return True 772 773 def get(self, essl_level, glsl_level, shader_type, name): 774 if self.has_key(essl_level, glsl_level, shader_type, name): 775 name_hash = mangledNameHash(name, self.hashfn, None, True, False) 776 return self.objs[name_hash] 777 return None 778 779 def get_max_name_length(self): 780 return self.max_name_length 781 782 def get_array(self): 783 code = [] 784 for hash_val in range(0, self.num_names): 785 obj = self.objs[hash_val] 786 essl_level = obj['essl_level'] 787 glsl_level = obj['glsl_level'] 788 shader_type = 'Shader::' + obj['shader_type'] if obj[ 789 'shader_type'] != 'NONE' else 'Shader::ALL' 790 data = [] 791 data.append('"{name}"'.format(name=obj['name'])) 792 data.append("Ext::" + obj['essl_extension']) 793 data.append("Ext::" + obj['glsl_extension']) 794 data.append(get_essl_shader_version_for_level(essl_level)) 795 data.append(get_glsl_shader_version_for_level(glsl_level)) 796 data.append(shader_type) 797 798 code.append('{%s}' % ', '.join(data)) 799 return code 800 801 802class TType: 803 804 def __init__(self, glsl_header_type): 805 if isinstance(glsl_header_type, basestring): 806 self.data = self.parse_type(glsl_header_type) 807 else: 808 self.data = glsl_header_type 809 self.normalize() 810 811 def normalize(self): 812 # Note that this will set primarySize and secondarySize also on genTypes. In that case they 813 # are overridden when the specific types are generated. 814 if 'primarySize' not in self.data: 815 if ('secondarySize' in self.data): 816 raise Exception( 817 'Unexpected secondarySize on type that does not have primarySize set') 818 self.data['primarySize'] = 1 819 if 'secondarySize' not in self.data: 820 self.data['secondarySize'] = 1 821 if 'precision' not in self.data: 822 self.data['precision'] = 'Undefined' 823 if 'qualifier' not in self.data: 824 self.data['qualifier'] = 'Global' 825 826 def has_array_size(self): 827 return 'arraySize' in self.data 828 829 def get_statictype_string(self): 830 template_type = 'StaticType::Get<Ebt{basic}, Ebp{precision}, Evq{qualifier}, {primarySize}, {secondarySize}>()' 831 if self.has_array_size(): 832 template_type = 'StaticType::GetArray<Ebt{basic}, Ebp{precision}, Evq{qualifier}, {primarySize}, {secondarySize}, kArraySize{arraySize}, 1>()' 833 return template_type.format(**self.data) 834 835 def get_dynamic_type_string(self): 836 template_type = 'new TType(Ebt{basic}, Ebp{precision}, Evq{qualifier}, {primarySize}, {secondarySize}' 837 if self.has_array_size(): 838 template_type += ', TVector<unsigned int>{{{arraySize}}}' 839 template_type += ')' 840 return template_type.format(**self.data) 841 842 def get_mangled_name(self): 843 mangled_name = '' 844 845 size_key = (self.data['secondarySize'] - 1) * 4 + self.data['primarySize'] - 1 846 if size_key < 10: 847 mangled_name += chr(ord('0') + size_key) 848 else: 849 mangled_name += chr(ord('A') + size_key - 10) 850 mangled_name += get_basic_mangled_name(self.data['basic']) 851 if self.has_array_size(): 852 mangled_name += 'x' + str(self.data['arraySize']) 853 return mangled_name 854 855 def get_human_readable_name(self): 856 name = self.data['basic'] 857 if self.has_array_size(): 858 name = str(self.data['arraySize']) + 'x' + name 859 name += str(self.data['primarySize']) 860 if self.data['secondarySize'] > 1: 861 name += 'x' + str(self.data['secondarySize']) 862 return name 863 864 def is_vector(self): 865 return self.data['primarySize'] > 1 and self.data['secondarySize'] == 1 866 867 def is_matrix(self): 868 return self.data['secondarySize'] > 1 869 870 def get_object_size(self): 871 return self.data['primarySize'] * self.data['secondarySize'] 872 873 def specific_sampler_or_image_or_subpass_type(self, basic_type_prefix): 874 if 'genType' in self.data and self.data['genType'] == 'sampler_or_image_or_subpass': 875 type = {} 876 if 'basic' not in self.data: 877 type['basic'] = {'': 'Float', 'I': 'Int', 'U': 'UInt'}[basic_type_prefix] 878 type['primarySize'] = self.data['primarySize'] 879 else: 880 type['basic'] = basic_type_prefix + self.data['basic'] 881 type['primarySize'] = 1 882 type['precision'] = 'Undefined' 883 return TType(type) 884 return self 885 886 def specific_type(self, vec_size): 887 type = {} 888 if 'genType' in self.data: 889 type['basic'] = self.data['basic'] 890 type['precision'] = self.data['precision'] 891 type['qualifier'] = self.data['qualifier'] 892 type['primarySize'] = vec_size 893 type['secondarySize'] = 1 894 return TType(type) 895 return self 896 897 def parse_type(self, glsl_header_type): 898 # TODO(http://anglebug.com/3833): handle readonly, writeonly qualifiers 899 if glsl_header_type.startswith('readonly writeonly '): 900 type_obj = self.parse_type(glsl_header_type[19:]) 901 type_obj['qualifier'] = 'Readonly Writeonly' 902 return type_obj 903 if glsl_header_type.startswith('readonly '): 904 type_obj = self.parse_type(glsl_header_type[9:]) 905 type_obj['qualifier'] = 'Readonly' 906 return type_obj 907 if glsl_header_type.startswith('writeonly '): 908 type_obj = self.parse_type(glsl_header_type[10:]) 909 type_obj['qualifier'] = 'Writeonly' 910 return type_obj 911 if glsl_header_type.startswith('out '): 912 type_obj = self.parse_type(glsl_header_type[4:]) 913 type_obj['qualifier'] = 'Out' 914 return type_obj 915 if glsl_header_type.startswith('inout '): 916 type_obj = self.parse_type(glsl_header_type[6:]) 917 type_obj['qualifier'] = 'InOut' 918 return type_obj 919 920 basic_type_map = { 921 'float': 'Float', 922 'int': 'Int', 923 'uint': 'UInt', 924 'double': 'Double', 925 'bool': 'Bool', 926 'void': 'Void', 927 'atomic_uint': 'AtomicCounter', 928 'yuvCscStandardEXT': 'YuvCscStandardEXT' 929 } 930 931 if glsl_header_type in basic_type_map: 932 return {'basic': basic_type_map[glsl_header_type]} 933 934 type_obj = {} 935 936 basic_type_prefix_map = { 937 '': 'Float', 938 'i': 'Int', 939 'u': 'UInt', 940 'd': 'Double', 941 'b': 'Bool', 942 'v': 'Void' 943 } 944 945 vec_re = re.compile(r'^([iudb]?)vec([234]?)((\[[234]\])?)$') 946 vec_match = vec_re.match(glsl_header_type) 947 if vec_match: 948 type_obj['basic'] = basic_type_prefix_map[vec_match.group(1)] 949 if vec_match.group(2) == '': 950 # Type like "ivec" that represents either ivec2, ivec3 or ivec4 951 type_obj['genType'] = 'vec' 952 else: 953 # vec with specific size 954 if vec_match.group(3) != '': 955 # vec array 956 type_obj['primarySize'] = int(vec_match.group(2)) 957 type_obj['arraySize'] = int(vec_match.group(3)[1]) 958 else: 959 type_obj['primarySize'] = int(vec_match.group(2)) 960 return type_obj 961 962 mat_re = re.compile(r'^mat([234])(x([234]))?$') 963 mat_match = mat_re.match(glsl_header_type) 964 if mat_match: 965 type_obj['basic'] = 'Float' 966 if len(glsl_header_type) == 4: 967 mat_size = int(mat_match.group(1)) 968 type_obj['primarySize'] = mat_size 969 type_obj['secondarySize'] = mat_size 970 else: 971 type_obj['primarySize'] = int(mat_match.group(1)) 972 type_obj['secondarySize'] = int(mat_match.group(3)) 973 return type_obj 974 975 gen_re = re.compile(r'^gen([IUDB]?)Type$') 976 gen_match = gen_re.match(glsl_header_type) 977 if gen_match: 978 type_obj['basic'] = basic_type_prefix_map[gen_match.group(1).lower()] 979 type_obj['genType'] = 'yes' 980 return type_obj 981 982 if glsl_header_type.startswith('sampler'): 983 type_obj['basic'] = glsl_header_type[0].upper() + glsl_header_type[1:] 984 return type_obj 985 986 if glsl_header_type.startswith('gsampler') or glsl_header_type.startswith( 987 'gimage') or glsl_header_type.startswith('gsubpassInput'): 988 type_obj['basic'] = glsl_header_type[1].upper() + glsl_header_type[2:] 989 type_obj['genType'] = 'sampler_or_image_or_subpass' 990 return type_obj 991 992 if glsl_header_type == 'gvec4': 993 return {'primarySize': 4, 'genType': 'sampler_or_image_or_subpass'} 994 if glsl_header_type == 'gvec3': 995 return {'primarySize': 3, 'genType': 'sampler_or_image_or_subpass'} 996 997 if glsl_header_type == 'IMAGE_PARAMS': 998 return {'genType': 'image_params'} 999 1000 raise Exception('Unrecognized type: ' + str(glsl_header_type)) 1001 1002 1003class HashFunction: 1004 1005 def __init__(self, f1, f2, G): 1006 self.f1 = f1 1007 self.f2 = f2 1008 self.G = G 1009 1010 def hash(self, key): 1011 return (self.G[self.f1(key)] + self.G[self.f2(key)]) % len(self.G) 1012 1013 1014def get_parsed_functions(functions_txt_filename, essl_only): 1015 1016 def parse_function_parameters(parameters): 1017 if parameters == '': 1018 return [] 1019 parametersOut = [] 1020 parameters = parameters.split(', ') 1021 for parameter in parameters: 1022 parametersOut.append(TType(parameter.strip())) 1023 return parametersOut 1024 1025 lines = [] 1026 with open(functions_txt_filename) as f: 1027 lines = f.readlines() 1028 lines = [ 1029 line.strip() for line in lines if line.strip() != '' and not line.strip().startswith('//') 1030 ] 1031 1032 fun_re = re.compile(r'^(\w+) (\w+)\((.*)\);$') 1033 1034 parsed_functions = OrderedDict() 1035 group_stack = [] 1036 default_metadata = {} 1037 1038 for line in lines: 1039 fun_match = fun_re.match(line) 1040 if line.startswith('GROUP BEGIN '): 1041 group_rest = line[12:].strip() 1042 group_parts = group_rest.split(' ', 1) 1043 current_group = {'functions': [], 'name': group_parts[0], 'subgroups': {}} 1044 if len(group_parts) > 1: 1045 group_metadata = json.loads(group_parts[1]) 1046 current_group.update(group_metadata) 1047 group_stack.append(current_group) 1048 elif line.startswith('GROUP END '): 1049 group_end_name = line[10:].strip() 1050 current_group = group_stack[-1] 1051 if current_group['name'] != group_end_name: 1052 raise Exception('GROUP END: Unexpected function group name "' + group_end_name + 1053 '" was expecting "' + current_group['name'] + '"') 1054 group_stack.pop() 1055 is_top_level_group = (len(group_stack) == 0) 1056 if is_top_level_group: 1057 parsed_functions[current_group['name']] = current_group 1058 default_metadata = {} 1059 else: 1060 super_group = group_stack[-1] 1061 super_group['subgroups'][current_group['name']] = current_group 1062 elif line.startswith('DEFAULT METADATA'): 1063 line_rest = line[16:].strip() 1064 default_metadata = json.loads(line_rest) 1065 elif fun_match: 1066 return_type = fun_match.group(1) 1067 name = fun_match.group(2) 1068 parameters = fun_match.group(3) 1069 function_props = { 1070 'name': name, 1071 'returnType': TType(return_type), 1072 'parameters': parse_function_parameters(parameters) 1073 } 1074 function_props.update(default_metadata) 1075 if essl_only: 1076 # Skip GLSL-only functions 1077 if 'essl_level' in function_props: 1078 group_stack[-1]['functions'].append(function_props) 1079 else: 1080 group_stack[-1]['functions'].append(function_props) 1081 else: 1082 raise Exception('Unexpected function input line: ' + line) 1083 1084 return parsed_functions 1085 1086 1087def mangledNameHash(str, hashfn, script_generated_hash_tests, unmangled, save_test=True): 1088 hash = hashfn.hash(str) 1089 if save_test: 1090 sanity_check = '' 1091 if unmangled: 1092 sanity_check = ' ASSERT_EQ(0x{hash}u, ImmutableString("{str}").unmangledNameHash());'.format( 1093 hash=('%08x' % hash), str=str) 1094 else: 1095 sanity_check = ' ASSERT_EQ(0x{hash}u, ImmutableString("{str}").mangledNameHash());'.format( 1096 hash=('%08x' % hash), str=str) 1097 script_generated_hash_tests.update({sanity_check: None}) 1098 return hash 1099 1100 1101def get_function_names(group, mangled_names, unmangled_names): 1102 if 'functions' in group: 1103 for function_props in group['functions']: 1104 function_name = function_props['name'] 1105 unmangled_names.append(function_name) 1106 function_variants = gen_function_variants(function_props) 1107 for function_props in function_variants: 1108 parameters = get_parameters(function_props) 1109 mangled_names.append(get_function_mangled_name(function_name, parameters)) 1110 if 'subgroups' in group: 1111 for subgroup_name, subgroup in group['subgroups'].iteritems(): 1112 get_function_names(subgroup, mangled_names, unmangled_names) 1113 1114 1115def get_variable_names(group, mangled_names): 1116 if 'variables' in group: 1117 for variable_name, props in group['variables'].iteritems(): 1118 mangled_names.append(variable_name) 1119 if 'subgroups' in group: 1120 for subgroup_name, subgroup in group['subgroups'].iteritems(): 1121 get_variable_names(subgroup, mangled_names) 1122 1123 1124def get_suffix(props): 1125 if 'suffix' in props: 1126 return props['suffix'] 1127 return '' 1128 1129 1130def get_essl_extension(props): 1131 if 'essl_extension' in props: 1132 return props['essl_extension'] 1133 return 'UNDEFINED' 1134 1135 1136def get_glsl_extension(props): 1137 if 'glsl_extension' in props: 1138 return props['glsl_extension'] 1139 return 'UNDEFINED' 1140 1141 1142def get_op(name, function_props): 1143 if 'op' not in function_props: 1144 raise Exception('function op not defined') 1145 if function_props['op'] == 'auto': 1146 return name[0].upper() + name[1:] 1147 return function_props['op'] 1148 1149 1150def get_known_to_not_have_side_effects(function_props): 1151 if 'op' in function_props and function_props['op'] != 'CallBuiltInFunction': 1152 if 'hasSideEffects' in function_props: 1153 return 'false' 1154 else: 1155 for param in get_parameters(function_props): 1156 if 'qualifier' in param.data and (param.data['qualifier'] == 'Out' or 1157 param.data['qualifier'] == 'InOut'): 1158 return 'false' 1159 return 'true' 1160 return 'false' 1161 1162 1163def get_parameters(function_props): 1164 if 'parameters' in function_props: 1165 return function_props['parameters'] 1166 return [] 1167 1168 1169def get_function_mangled_name(function_name, parameters): 1170 mangled_name = function_name + '(' 1171 for param in parameters: 1172 mangled_name += param.get_mangled_name() 1173 return mangled_name 1174 1175 1176def get_function_human_readable_name(function_name, parameters): 1177 name = function_name 1178 for param in parameters: 1179 name += '_' + param.get_human_readable_name() 1180 return name 1181 1182 1183def get_unique_identifier_name(function_name, parameters): 1184 unique_name = function_name + '_' 1185 for param in parameters: 1186 unique_name += param.get_mangled_name() 1187 return unique_name 1188 1189 1190def get_variable_name_to_store_parameter(param): 1191 unique_name = 'pt' 1192 if 'qualifier' in param.data: 1193 if param.data['qualifier'] == 'Out': 1194 unique_name += '_o_' 1195 if param.data['qualifier'] == 'InOut': 1196 unique_name += '_io_' 1197 unique_name += param.get_mangled_name() 1198 return unique_name 1199 1200 1201def get_variable_name_to_store_parameters(parameters): 1202 if len(parameters) == 0: 1203 return 'empty' 1204 unique_name = 'p' 1205 for param in parameters: 1206 if 'qualifier' in param.data: 1207 if param.data['qualifier'] == 'Out': 1208 unique_name += '_o_' 1209 if param.data['qualifier'] == 'InOut': 1210 unique_name += '_io_' 1211 unique_name += param.get_mangled_name() 1212 return unique_name 1213 1214 1215def define_constexpr_type_array_sizes(template_args, type_array_sizes_declarations): 1216 template_array_sizes_declaration = 'constexpr const unsigned int kArraySize{arraySize}[1] = {{{arraySize}}};' 1217 type_array_sizes_declarations.add(template_array_sizes_declaration.format(**template_args)) 1218 1219 1220def define_constexpr_variable(template_args, variable_declarations): 1221 template_variable_declaration = 'constexpr const TVariable k{name_with_suffix}(BuiltInId::{name_with_suffix}, BuiltInName::{name}, SymbolType::BuiltIn, TExtension::{extension}, {type});' 1222 variable_declarations.append(template_variable_declaration.format(**template_args)) 1223 1224 1225def gen_function_variants(function_props): 1226 function_variants = [] 1227 parameters = get_parameters(function_props) 1228 function_is_gen_type = False 1229 gen_type = set() 1230 image_params_index = 0 1231 for param in parameters + [function_props['returnType']]: 1232 if 'genType' in param.data: 1233 if param.data['genType'] not in [ 1234 'sampler_or_image_or_subpass', 'vec', 'yes', 'image_params' 1235 ]: 1236 raise Exception( 1237 'Unexpected value of genType "' + str(param.data['genType']) + 1238 '" should be "sampler_or_image_or_subpass", "vec", "yes", or "image_params"') 1239 gen_type.add(param.data['genType']) 1240 if param.data['genType'] == 'image_params': 1241 image_params_index = parameters.index(param) 1242 1243 if len(gen_type) == 0: 1244 function_variants.append(function_props) 1245 return function_variants 1246 1247 # If we have image_params then we're generating variants for 33 separate functions, 1248 # each for a different type of image variable 1249 if 'image_params' in gen_type: 1250 variants = [['gimage2D', 'ivec2'], ['gimage3D', 'ivec3'], ['gimageCube', 'ivec3'], 1251 ['gimageBuffer', 'int'], ['gimage2DArray', 'ivec3'], 1252 ['gimageCubeArray', 'ivec3'], ['gimage1D', 'int'], ['gimage1DArray', 'ivec2'], 1253 ['gimage2DRect', 'ivec2'], ['gimage2DMS', 'ivec2', 'int'], 1254 ['gimage2DMSArray', 'ivec3', 'int']] 1255 for variant in variants: 1256 image_variant_parameters = [] 1257 for param in parameters: 1258 if parameters.index(param) == image_params_index: 1259 for variant_param in variant: 1260 image_variant_parameters.append(TType(variant_param)) 1261 else: 1262 image_variant_parameters.append(param) 1263 types = ['', 'I', 'U'] 1264 for type in types: 1265 variant_props = function_props.copy() 1266 variant_parameters = [] 1267 for param in image_variant_parameters: 1268 variant_parameters.append( 1269 param.specific_sampler_or_image_or_subpass_type(type)) 1270 variant_props['parameters'] = variant_parameters 1271 variant_props['returnType'] = function_props[ 1272 'returnType'].specific_sampler_or_image_or_subpass_type(type) 1273 function_variants.append(variant_props) 1274 return function_variants 1275 1276 # If we have a gsampler_or_image_or_subpass then we're generating variants for float, int and uint 1277 # samplers. 1278 if 'sampler_or_image_or_subpass' in gen_type: 1279 types = ['', 'I', 'U'] 1280 for type in types: 1281 variant_props = function_props.copy() 1282 variant_parameters = [] 1283 for param in parameters: 1284 variant_parameters.append(param.specific_sampler_or_image_or_subpass_type(type)) 1285 variant_props['parameters'] = variant_parameters 1286 variant_props['returnType'] = function_props[ 1287 'returnType'].specific_sampler_or_image_or_subpass_type(type) 1288 function_variants.append(variant_props) 1289 return function_variants 1290 1291 # If we have a normal gentype then we're generating variants for different sizes of vectors. 1292 sizes = range(1, 5) 1293 if 'vec' in gen_type: 1294 sizes = range(2, 5) 1295 for size in sizes: 1296 variant_props = function_props.copy() 1297 variant_parameters = [] 1298 for param in parameters: 1299 variant_parameters.append(param.specific_type(size)) 1300 variant_props['parameters'] = variant_parameters 1301 variant_props['returnType'] = function_props['returnType'].specific_type(size) 1302 function_variants.append(variant_props) 1303 return function_variants 1304 1305 1306def process_single_function_group( 1307 shader_type, group_name, group, parameter_declarations, name_declarations, 1308 unmangled_function_if_statements, defined_function_variants, builtin_id_declarations, 1309 builtin_id_definitions, defined_parameter_names, type_array_sizes_declarations, 1310 variable_declarations, function_declarations, script_generated_hash_tests, 1311 unmangled_script_generated_hash_tests, mangled_builtins): 1312 global id_counter 1313 1314 if 'functions' not in group: 1315 return 1316 1317 for function_props in group['functions']: 1318 function_name = function_props['name'] 1319 essl_level = function_props['essl_level'] if 'essl_level' in function_props else None 1320 glsl_level = function_props['glsl_level'] if 'glsl_level' in function_props else None 1321 essl_extension = get_essl_extension(function_props) 1322 glsl_extension = get_glsl_extension(function_props) 1323 extension = essl_extension if essl_extension != 'UNDEFINED' else glsl_extension 1324 template_args = { 1325 'name': function_name, 1326 'name_with_suffix': function_name + get_suffix(function_props), 1327 'essl_level': essl_level, 1328 'glsl_level': glsl_level, 1329 'essl_extension': essl_extension, 1330 'glsl_extension': glsl_extension, 1331 # This assumes that functions cannot be part of an ESSL and GLSL extension 1332 # Will need to update after adding GLSL extension functions if this is not the case 1333 'extension': essl_extension if essl_extension != 'UNDEFINED' else glsl_extension, 1334 'op': get_op(function_name, function_props), 1335 'known_to_not_have_side_effects': get_known_to_not_have_side_effects(function_props) 1336 } 1337 1338 function_variants = gen_function_variants(function_props) 1339 1340 template_name_declaration = 'constexpr const ImmutableString {name_with_suffix}("{name}");' 1341 name_declaration = template_name_declaration.format(**template_args) 1342 if not name_declaration in name_declarations: 1343 name_declarations.add(name_declaration) 1344 1345 essl_ext = '{essl_extension}'.format(**template_args) 1346 glsl_ext = '{glsl_extension}'.format(**template_args) 1347 unmangled_builtin_no_shader_type = unmangled_function_if_statements.get( 1348 essl_level, glsl_level, 'NONE', function_name) 1349 if unmangled_builtin_no_shader_type != None and unmangled_builtin_no_shader_type[ 1350 'essl_extension'] == 'UNDEFINED' and unmangled_builtin_no_shader_type[ 1351 'glsl_extension'] == 'UNDEFINED': 1352 # We already have this unmangled name without a shader type nor extension on the same level. 1353 # No need to add a duplicate with a type. 1354 pass 1355 elif (not unmangled_function_if_statements.has_key( 1356 essl_level, glsl_level, shader_type, function_name)) or ( 1357 unmangled_builtin_no_shader_type and 1358 ((essl_extension == 'UNDEFINED' and 1359 unmangled_builtin_no_shader_type['essl_extension'] != 'UNDEFINED') or 1360 (glsl_extension == 'UNDEFINED' and 1361 unmangled_builtin_no_shader_type['glsl_extension'] != 'UNDEFINED'))): 1362 unmangled_function_if_statements.add_entry( 1363 essl_level, glsl_level, shader_type, function_name, essl_ext, glsl_ext, 1364 essl_extension, glsl_extension, unmangled_script_generated_hash_tests) 1365 1366 for function_props in function_variants: 1367 template_args['id'] = id_counter 1368 1369 parameters = get_parameters(function_props) 1370 1371 template_args['unique_name'] = get_unique_identifier_name( 1372 template_args['name_with_suffix'], parameters) 1373 template_args['param_count'] = len(parameters) 1374 template_args['return_type'] = function_props['returnType'].get_statictype_string() 1375 template_args['mangled_name'] = get_function_mangled_name(function_name, parameters) 1376 template_args['human_readable_name'] = get_function_human_readable_name( 1377 template_args['name_with_suffix'], parameters) 1378 template_args['mangled_name_length'] = len(template_args['mangled_name']) 1379 1380 symbol = '&Func::{unique_name}'.format(**template_args) 1381 mangled_builtins.add_entry( 1382 essl_level, glsl_level, shader_type, template_args['mangled_name'], symbol, 1383 template_args['essl_extension'], template_args['glsl_extension'], 1384 script_generated_hash_tests) 1385 1386 if template_args['unique_name'] in defined_function_variants: 1387 continue 1388 defined_function_variants.add(template_args['unique_name']) 1389 1390 template_builtin_id_declaration = ' static constexpr const TSymbolUniqueId {human_readable_name} = TSymbolUniqueId({id});' 1391 builtin_id_declarations.append(template_builtin_id_declaration.format(**template_args)) 1392 template_builtin_id_definition = 'constexpr const TSymbolUniqueId BuiltInId::{human_readable_name};' 1393 builtin_id_definitions.append(template_builtin_id_definition.format(**template_args)) 1394 1395 parameters_list = [] 1396 for param in parameters: 1397 unique_param_name = get_variable_name_to_store_parameter(param) 1398 param_template_args = { 1399 'name': '_empty', 1400 'name_with_suffix': unique_param_name, 1401 'type': param.get_statictype_string(), 1402 'extension': 'UNDEFINED' 1403 } 1404 if unique_param_name not in defined_parameter_names: 1405 id_counter += 1 1406 param_template_args['id'] = id_counter 1407 template_builtin_id_declaration = ' static constexpr const TSymbolUniqueId {name_with_suffix} = TSymbolUniqueId({id});' 1408 builtin_id_declarations.append( 1409 template_builtin_id_declaration.format(**param_template_args)) 1410 define_constexpr_variable(param_template_args, variable_declarations) 1411 defined_parameter_names.add(unique_param_name) 1412 if param.has_array_size(): 1413 array_size_template_args = {'arraySize': param.data['arraySize']} 1414 define_constexpr_type_array_sizes(array_size_template_args, 1415 type_array_sizes_declarations) 1416 parameters_list.append( 1417 '&BuiltInVariable::k{name_with_suffix}'.format(**param_template_args)) 1418 1419 template_args['parameters_var_name'] = get_variable_name_to_store_parameters( 1420 parameters) 1421 if len(parameters) > 0: 1422 template_args['parameters_list'] = ', '.join(parameters_list) 1423 template_parameter_list_declaration = 'constexpr const TVariable *{parameters_var_name}[{param_count}] = {{ {parameters_list} }};' 1424 parameter_declarations[template_args[ 1425 'parameters_var_name']] = template_parameter_list_declaration.format( 1426 **template_args) 1427 else: 1428 template_parameter_list_declaration = 'constexpr const TVariable **{parameters_var_name} = nullptr;' 1429 parameter_declarations[template_args[ 1430 'parameters_var_name']] = template_parameter_list_declaration.format( 1431 **template_args) 1432 1433 template_function_declaration = 'constexpr const TFunction {unique_name}(BuiltInId::{human_readable_name}, BuiltInName::{name_with_suffix}, TExtension::{extension}, BuiltInParameters::{parameters_var_name}, {param_count}, {return_type}, EOp{op}, {known_to_not_have_side_effects});' 1434 function_declarations.append(template_function_declaration.format(**template_args)) 1435 1436 id_counter += 1 1437 1438 1439def process_function_group( 1440 group_name, group, parameter_declarations, name_declarations, 1441 unmangled_function_if_statements, defined_function_variants, builtin_id_declarations, 1442 builtin_id_definitions, defined_parameter_names, type_array_sizes_declarations, 1443 variable_declarations, function_declarations, script_generated_hash_tests, 1444 unmangled_script_generated_hash_tests, mangled_builtins, is_in_group_definitions): 1445 global id_counter 1446 first_id = id_counter 1447 1448 shader_type = 'NONE' 1449 if 'shader_type' in group: 1450 shader_type = group['shader_type'] 1451 1452 process_single_function_group( 1453 shader_type, group_name, group, parameter_declarations, name_declarations, 1454 unmangled_function_if_statements, defined_function_variants, builtin_id_declarations, 1455 builtin_id_definitions, defined_parameter_names, type_array_sizes_declarations, 1456 variable_declarations, function_declarations, script_generated_hash_tests, 1457 unmangled_script_generated_hash_tests, mangled_builtins) 1458 1459 if 'subgroups' in group: 1460 for subgroup_name, subgroup in group['subgroups'].iteritems(): 1461 process_function_group( 1462 group_name + subgroup_name, subgroup, parameter_declarations, name_declarations, 1463 unmangled_function_if_statements, defined_function_variants, 1464 builtin_id_declarations, builtin_id_definitions, defined_parameter_names, 1465 type_array_sizes_declarations, variable_declarations, function_declarations, 1466 script_generated_hash_tests, unmangled_script_generated_hash_tests, 1467 mangled_builtins, is_in_group_definitions) 1468 1469 if 'queryFunction' in group: 1470 template_args = {'first_id': first_id, 'last_id': id_counter - 1, 'group_name': group_name} 1471 template_is_in_group_definition = """bool is{group_name}(const TFunction *func) 1472{{ 1473 int id = func->uniqueId().get(); 1474 return id >= {first_id} && id <= {last_id}; 1475}}""" 1476 is_in_group_definitions.append(template_is_in_group_definition.format(**template_args)) 1477 1478 1479def prune_parameters_arrays(parameter_declarations, function_declarations): 1480 # We can share parameters arrays between functions in case one array is a subarray of another. 1481 parameter_variable_name_replacements = {} 1482 used_param_variable_names = set() 1483 for param_variable_name, param_declaration in sorted( 1484 parameter_declarations.iteritems(), key=lambda item: -len(item[0])): 1485 replaced = False 1486 for used in used_param_variable_names: 1487 if used.startswith(param_variable_name): 1488 parameter_variable_name_replacements[param_variable_name] = used 1489 replaced = True 1490 break 1491 if not replaced: 1492 used_param_variable_names.add(param_variable_name) 1493 1494 for i in xrange(len(function_declarations)): 1495 for replaced, replacement in parameter_variable_name_replacements.iteritems(): 1496 function_declarations[i] = function_declarations[i].replace( 1497 'BuiltInParameters::' + replaced + ',', 'BuiltInParameters::' + replacement + ',') 1498 1499 return [ 1500 value for key, value in parameter_declarations.iteritems() 1501 if key in used_param_variable_names 1502 ] 1503 1504 1505def process_single_variable_group(shader_type, group_name, group, builtin_id_declarations, 1506 builtin_id_definitions, name_declarations, init_member_variables, 1507 get_variable_declarations, mangled_builtins, 1508 declare_member_variables, variable_declarations, 1509 get_variable_definitions, script_generated_hash_tests): 1510 global id_counter 1511 if 'variables' not in group: 1512 return 1513 for variable_name, props in group['variables'].iteritems(): 1514 essl_level = props['essl_level'] if 'essl_level' in props else None 1515 glsl_level = props['glsl_level'] if 'glsl_level' in props else None 1516 template_args = { 1517 'id': 1518 id_counter, 1519 'name': 1520 variable_name, 1521 'name_with_suffix': 1522 variable_name + get_suffix(props), 1523 'essl_level': 1524 essl_level, 1525 'glsl_level': 1526 glsl_level, 1527 'essl_extension': 1528 get_essl_extension(props), 1529 'glsl_extension': 1530 get_glsl_extension(props), 1531 # This assumes that variables cannot be part of an ESSL and GLSL extension 1532 # Will need to update after adding GLSL extension variables if this is not the case 1533 'extension': 1534 get_essl_extension(props) 1535 if get_essl_extension(props) != 'UNDEFINED' else get_glsl_extension(props), 1536 'class': 1537 'TVariable' 1538 } 1539 1540 template_builtin_id_declaration = ' static constexpr const TSymbolUniqueId {name_with_suffix} = TSymbolUniqueId({id});' 1541 builtin_id_declarations.append(template_builtin_id_declaration.format(**template_args)) 1542 template_builtin_id_definition = 'constexpr const TSymbolUniqueId BuiltInId::{name_with_suffix};' 1543 builtin_id_definitions.append(template_builtin_id_definition.format(**template_args)) 1544 1545 template_name_declaration = 'constexpr const ImmutableString {name}("{name}");' 1546 name_declarations.add(template_name_declaration.format(**template_args)) 1547 1548 is_member = True 1549 template_init_variable = '' 1550 1551 if 'type' in props: 1552 if props['type']['basic'] != 'Bool' and 'precision' not in props['type']: 1553 raise Exception('Missing precision for variable ' + variable_name) 1554 template_args['type'] = TType(props['type']).get_statictype_string() 1555 1556 if 'fields' in props: 1557 # Handle struct and interface block definitions. 1558 template_args['class'] = props['class'] 1559 template_args['fields'] = 'fields_{name_with_suffix}'.format(**template_args) 1560 init_member_variables.append( 1561 ' TFieldList *{fields} = new TFieldList();'.format(**template_args)) 1562 for field_name, field_type in props['fields'].iteritems(): 1563 template_args['field_name'] = field_name 1564 template_args['field_type'] = TType(field_type).get_dynamic_type_string() 1565 template_name_declaration = 'constexpr const ImmutableString {field_name}("{field_name}");' 1566 name_declarations.add(template_name_declaration.format(**template_args)) 1567 template_add_field = ' {fields}->push_back(new TField({field_type}, BuiltInName::{field_name}, zeroSourceLoc, SymbolType::BuiltIn));' 1568 init_member_variables.append(template_add_field.format(**template_args)) 1569 template_init_temp_variable = ' {class} *{name_with_suffix} = new {class}(BuiltInId::{name_with_suffix}, BuiltInName::{name}, TExtension::{extension}, {fields});' 1570 init_member_variables.append(template_init_temp_variable.format(**template_args)) 1571 if 'private' in props and props['private']: 1572 is_member = False 1573 else: 1574 template_init_variable = ' m_{name_with_suffix} = {name_with_suffix};' 1575 1576 elif 'initDynamicType' in props: 1577 # Handle variables whose type can't be expressed as TStaticType 1578 # (type is a struct or has variable array size for example). 1579 template_args['type_name'] = 'type_{name_with_suffix}'.format(**template_args) 1580 template_args['type'] = template_args['type_name'] 1581 template_args['initDynamicType'] = props['initDynamicType'].format(**template_args) 1582 template_init_variable = """ {initDynamicType} 1583 {type_name}->realize(); 1584 m_{name_with_suffix} = new TVariable(BuiltInId::{name_with_suffix}, BuiltInName::{name}, SymbolType::BuiltIn, TExtension::{extension}, {type});""" 1585 1586 elif 'value' in props: 1587 # Handle variables with constant value, such as gl_MaxDrawBuffers. 1588 if props['value'] != 'resources': 1589 raise Exception('Unrecognized value source in variable properties: ' + 1590 str(props['value'])) 1591 resources_key = variable_name[3:] 1592 if 'valueKey' in props: 1593 resources_key = props['valueKey'] 1594 template_args['value'] = 'resources.' + resources_key 1595 template_args['object_size'] = TType(props['type']).get_object_size() 1596 template_init_variable = """ m_{name_with_suffix} = new TVariable(BuiltInId::{name_with_suffix}, BuiltInName::{name}, SymbolType::BuiltIn, TExtension::{extension}, {type}); 1597 {{ 1598 TConstantUnion *unionArray = new TConstantUnion[{object_size}]; 1599 unionArray[0].setIConst({value}); 1600 static_cast<TVariable *>(m_{name_with_suffix})->shareConstPointer(unionArray); 1601 }}""" 1602 if template_args['object_size'] > 1: 1603 template_init_variable = """ m_{name_with_suffix} = new TVariable(BuiltInId::{name_with_suffix}, BuiltInName::{name}, SymbolType::BuiltIn, TExtension::{extension}, {type}); 1604 {{ 1605 TConstantUnion *unionArray = new TConstantUnion[{object_size}]; 1606 for (size_t index = 0u; index < {object_size}; ++index) 1607 {{ 1608 unionArray[index].setIConst({value}[index]); 1609 }} 1610 static_cast<TVariable *>(m_{name_with_suffix})->shareConstPointer(unionArray); 1611 }}""" 1612 1613 else: 1614 # Handle variables that can be stored as constexpr TVariable like 1615 # gl_Position, gl_FragColor etc. 1616 define_constexpr_variable(template_args, variable_declarations) 1617 is_member = False 1618 1619 template_get_variable_declaration = 'const TVariable *{name_with_suffix}();' 1620 get_variable_declarations.append( 1621 template_get_variable_declaration.format(**template_args)) 1622 1623 template_get_variable_definition = """const TVariable *{name_with_suffix}() 1624{{ 1625 return &k{name_with_suffix}; 1626}} 1627""" 1628 get_variable_definitions.append( 1629 template_get_variable_definition.format(**template_args)) 1630 1631 if essl_level != 'GLSL_BUILTINS': 1632 obj = '&BuiltInVariable::k{name_with_suffix}'.format(**template_args) 1633 # TODO(http://anglebug.com/3835): Add GLSL level once GLSL built-in vars are added 1634 mangled_builtins.add_entry( 1635 essl_level, 'COMMON_BUILTINS', shader_type, template_args['name'], obj, 1636 template_args['essl_extension'], template_args['glsl_extension'], 1637 script_generated_hash_tests) 1638 1639 if is_member: 1640 init_member_variables.append(template_init_variable.format(**template_args)) 1641 1642 template_declare_member_variable = 'TSymbol *m_{name_with_suffix} = nullptr;' 1643 declare_member_variables.append( 1644 template_declare_member_variable.format(**template_args)) 1645 1646 obj = 'm_{name_with_suffix}'.format(**template_args) 1647 1648 # TODO(http://anglebug.com/3835): Add GLSL level once GLSL built-in vars are added 1649 mangled_builtins.add_entry(essl_level, 'COMMON_BUILTINS', shader_type, 1650 template_args['name'], obj, template_args['essl_extension'], 1651 template_args['glsl_extension'], 1652 script_generated_hash_tests) 1653 1654 id_counter += 1 1655 1656 1657def process_variable_group(shader_type, group_name, group, builtin_id_declarations, 1658 builtin_id_definitions, name_declarations, init_member_variables, 1659 get_variable_declarations, mangled_builtins, declare_member_variables, 1660 variable_declarations, get_variable_definitions, 1661 script_generated_hash_tests): 1662 global id_counter 1663 1664 if 'shader_type' in group: 1665 shader_type = group['shader_type'] 1666 1667 process_single_variable_group(shader_type, group_name, group, builtin_id_declarations, 1668 builtin_id_definitions, name_declarations, init_member_variables, 1669 get_variable_declarations, mangled_builtins, 1670 declare_member_variables, variable_declarations, 1671 get_variable_definitions, script_generated_hash_tests) 1672 1673 if 'subgroups' in group: 1674 for subgroup_name, subgroup in group['subgroups'].iteritems(): 1675 process_variable_group( 1676 shader_type, subgroup_name, subgroup, builtin_id_declarations, 1677 builtin_id_definitions, name_declarations, init_member_variables, 1678 get_variable_declarations, mangled_builtins, declare_member_variables, 1679 variable_declarations, get_variable_definitions, script_generated_hash_tests) 1680 1681 1682def generate_files(essl_only, args, functions_txt_filename, variables_json_filename, 1683 immutablestring_cpp_filename, immutablestringtest_cpp_filename, 1684 builtin_header_filename, symboltable_cpp_filename, parsecontext_header_filename, 1685 symboltable_header_filename): 1686 # Declarations of symbol unique ids 1687 builtin_id_declarations = [] 1688 1689 # Definitions of symbol unique ids needed for those ids used outside of constexpr expressions. 1690 builtin_id_definitions = [] 1691 1692 # Declarations of name string variables 1693 name_declarations = set() 1694 1695 # Declarations of static array sizes if any builtin TVariable is array. 1696 type_array_sizes_declarations = set() 1697 1698 # Declarations of builtin TVariables 1699 variable_declarations = [] 1700 1701 # Declarations of builtin TFunctions 1702 function_declarations = [] 1703 1704 # Functions for querying the pointer to a specific TVariable. 1705 get_variable_declarations = [] 1706 get_variable_definitions = [] 1707 1708 # Code for defining TVariables stored as members of TSymbolTable. 1709 declare_member_variables = [] 1710 init_member_variables = [] 1711 1712 # Code for testing that script-generated hashes match with runtime computed hashes. 1713 script_generated_hash_tests = OrderedDict() 1714 unmangled_script_generated_hash_tests = OrderedDict() 1715 1716 # Functions for testing whether a builtin belongs in group. 1717 is_in_group_definitions = [] 1718 1719 # Declarations of parameter arrays for builtin TFunctions. Map from C++ variable name to the full 1720 # declaration. 1721 parameter_declarations = {} 1722 1723 defined_function_variants = set() 1724 defined_parameter_names = set() 1725 1726 parsed_functions = get_parsed_functions(functions_txt_filename, essl_only) 1727 1728 if args.dump_intermediate_json: 1729 with open('builtin_functions_ESSL.json' if essl_only else 'builtin_functions.json', 1730 'w') as outfile: 1731 1732 def serialize_obj(obj): 1733 if isinstance(obj, TType): 1734 return obj.data 1735 else: 1736 raise "Cannot serialize to JSON: " + str(obj) 1737 1738 json.dump( 1739 parsed_functions, outfile, indent=4, separators=(',', ': '), default=serialize_obj) 1740 1741 parsed_variables = None 1742 with open(variables_json_filename) as f: 1743 # TODO(http://anglebug.com/3835): skip loading GLSL-only vars when they are added if essl_only 1744 parsed_variables = json.load(f, object_pairs_hook=OrderedDict) 1745 1746 # This script uses a perfect hash function to avoid dealing with collisions 1747 mangled_names = [] 1748 unmangled_names = [] 1749 for group_name, group in parsed_functions.iteritems(): 1750 get_function_names(group, mangled_names, unmangled_names) 1751 for group_name, group in parsed_variables.iteritems(): 1752 get_variable_names(group, mangled_names) 1753 1754 # Hashing mangled names 1755 mangled_names = list(dict.fromkeys(mangled_names)) 1756 num_mangled_names = len(mangled_names) 1757 mangled_names_dict = dict(zip(mangled_names, range(0, len(mangled_names)))) 1758 # Generate the perfect hash function 1759 f1, f2, mangled_G = generate_hash(mangled_names_dict, Hash2) 1760 mangled_hashfn = HashFunction(f1, f2, mangled_G) 1761 mangled_S1 = f1.salt 1762 mangled_S2 = f2.salt 1763 # Array for querying mangled builtins 1764 mangled_builtins = GroupedList(mangled_hashfn, num_mangled_names) 1765 1766 # Hashing unmangled names 1767 unmangled_names = list(dict.fromkeys(unmangled_names)) 1768 num_unmangled_names = len(unmangled_names) 1769 unmangled_names_dict = dict(zip(unmangled_names, range(0, len(unmangled_names)))) 1770 # Generate the perfect hash function 1771 f1, f2, unmangled_G = generate_hash(unmangled_names_dict, Hash2) 1772 unmangled_hashfn = HashFunction(f1, f2, unmangled_G) 1773 unmangled_S1 = f1.salt 1774 unmangled_S2 = f2.salt 1775 # Array for querying unmangled builtins 1776 unmangled_function_if_statements = UnmangledGroupedList(unmangled_hashfn, num_unmangled_names) 1777 1778 for group_name, group in parsed_functions.iteritems(): 1779 process_function_group( 1780 group_name, group, parameter_declarations, name_declarations, 1781 unmangled_function_if_statements, defined_function_variants, builtin_id_declarations, 1782 builtin_id_definitions, defined_parameter_names, type_array_sizes_declarations, 1783 variable_declarations, function_declarations, script_generated_hash_tests, 1784 unmangled_script_generated_hash_tests, mangled_builtins, is_in_group_definitions) 1785 1786 parameter_declarations = prune_parameters_arrays(parameter_declarations, function_declarations) 1787 1788 for group_name, group in parsed_variables.iteritems(): 1789 process_variable_group('NONE', group_name, group, builtin_id_declarations, 1790 builtin_id_definitions, name_declarations, init_member_variables, 1791 get_variable_declarations, mangled_builtins, 1792 declare_member_variables, variable_declarations, 1793 get_variable_definitions, script_generated_hash_tests) 1794 1795 mangled_builtins.update_arrays() 1796 1797 output_strings = { 1798 'script_name': 1799 os.path.basename(__file__), 1800 'copyright_year': 1801 date.today().year, 1802 'builtin_id_declarations': 1803 '\n'.join(builtin_id_declarations), 1804 'builtin_id_definitions': 1805 '\n'.join(builtin_id_definitions), 1806 'last_builtin_id': 1807 id_counter - 1, 1808 'name_declarations': 1809 '\n'.join(sorted(list(name_declarations))), 1810 'function_data_source_name': 1811 functions_txt_filename, 1812 'function_declarations': 1813 '\n'.join(function_declarations), 1814 'parameter_declarations': 1815 '\n'.join(sorted(parameter_declarations)), 1816 'is_in_group_definitions': 1817 '\n'.join(is_in_group_definitions), 1818 'variable_data_source_name': 1819 variables_json_filename, 1820 'type_array_sizes_declarations': 1821 '\n'.join(sorted(type_array_sizes_declarations)), 1822 'variable_declarations': 1823 '\n'.join(sorted(variable_declarations)), 1824 'get_variable_declarations': 1825 '\n'.join(sorted(get_variable_declarations)), 1826 'get_variable_definitions': 1827 '\n'.join(sorted(get_variable_definitions)), 1828 'declare_member_variables': 1829 '\n'.join(declare_member_variables), 1830 'init_member_variables': 1831 '\n'.join(init_member_variables), 1832 'mangled_names_array': 1833 ',\n'.join(mangled_builtins.get_names()), 1834 'mangled_offsets_array': 1835 '\n'.join(mangled_builtins.get_offsets()), 1836 'mangled_rules': 1837 ',\n'.join(mangled_builtins.get_rules()), 1838 'unmangled_array': 1839 ', '.join(unmangled_function_if_statements.get_array()), 1840 'max_unmangled_name_length': 1841 unmangled_function_if_statements.get_max_name_length(), 1842 'max_mangled_name_length': 1843 mangled_builtins.get_max_name_length(), 1844 'num_unmangled_names': 1845 num_unmangled_names, 1846 'num_mangled_names': 1847 num_mangled_names, 1848 'script_generated_hash_tests': 1849 '\n'.join(script_generated_hash_tests.iterkeys()), 1850 'unmangled_script_generated_hash_tests': 1851 '\n'.join(unmangled_script_generated_hash_tests.iterkeys()), 1852 'mangled_S1': 1853 str(mangled_S1).replace('[', ' ').replace(']', ' '), 1854 'mangled_S2': 1855 str(mangled_S2).replace('[', ' ').replace(']', ' '), 1856 'mangled_G': 1857 str(mangled_G).replace('[', ' ').replace(']', ' '), 1858 'mangled_NG': 1859 len(mangled_G), 1860 'mangled_NS': 1861 len(mangled_S1), 1862 'unmangled_S1': 1863 str(unmangled_S1).replace('[', ' ').replace(']', ' '), 1864 'unmangled_S2': 1865 str(unmangled_S2).replace('[', ' ').replace(']', ' '), 1866 'unmangled_G': 1867 str(unmangled_G).replace('[', ' ').replace(']', ' '), 1868 'unmangled_NG': 1869 len(unmangled_G), 1870 'unmangled_NS': 1871 len(unmangled_S1), 1872 'header_label': 1873 'ESSL_' if essl_only else 'complete_', 1874 'source_label': 1875 'ESSL_' if essl_only else '' 1876 } 1877 1878 with open(immutablestring_cpp_filename, 'wt') as outfile_cpp: 1879 output_cpp = template_immutablestring_cpp.format(**output_strings) 1880 outfile_cpp.write(output_cpp) 1881 1882 with open(immutablestringtest_cpp_filename, 'wt') as outfile_cpp: 1883 output_cpp = template_immutablestringtest_cpp.format(**output_strings) 1884 outfile_cpp.write(output_cpp) 1885 1886 with open(builtin_header_filename, 'wt') as outfile_header: 1887 output_header = template_builtin_header.format(**output_strings) 1888 outfile_header.write(output_header) 1889 1890 with open(symboltable_cpp_filename, 'wt') as outfile_cpp: 1891 output_cpp = template_symboltable_cpp.format(**output_strings) 1892 outfile_cpp.write(output_cpp) 1893 1894 with open(parsecontext_header_filename, 'wt') as outfile_header: 1895 output_header = template_parsecontext_header.format(**output_strings) 1896 outfile_header.write(output_header) 1897 1898 if not essl_only: 1899 with open(symboltable_header_filename, 'wt') as outfile_h: 1900 output_h = template_symboltable_header.format(**output_strings) 1901 outfile_h.write(output_h) 1902 1903 1904def main(): 1905 random.seed(0) 1906 set_working_dir() 1907 1908 parser = argparse.ArgumentParser() 1909 parser.add_argument( 1910 '--dump-intermediate-json', 1911 help='Dump parsed function data as a JSON file builtin_functions.json', 1912 action="store_true") 1913 parser.add_argument('auto_script_command', nargs='?', default='') 1914 args = parser.parse_args() 1915 1916 test_filename = '../../tests/compiler_tests/ImmutableString_test_autogen.cpp' 1917 essl_test_filename = '../../tests/compiler_tests/ImmutableString_test_ESSL_autogen.cpp' 1918 variables_json_filename = 'builtin_variables.json' 1919 functions_txt_filename = 'builtin_function_declarations.txt' 1920 1921 # auto_script parameters. 1922 if args.auto_script_command != '': 1923 inputs = [ 1924 functions_txt_filename, 1925 variables_json_filename, 1926 ] 1927 outputs = [ 1928 'ImmutableString_autogen.cpp', 1929 'ParseContext_complete_autogen.h', 1930 'SymbolTable_autogen.cpp', 1931 'SymbolTable_autogen.h', 1932 'tree_util/BuiltIn_complete_autogen.h', 1933 test_filename, 1934 'ImmutableString_ESSL_autogen.cpp', 1935 'ParseContext_ESSL_autogen.h', 1936 'SymbolTable_ESSL_autogen.cpp', 1937 'tree_util/BuiltIn_ESSL_autogen.h', 1938 essl_test_filename, 1939 ] 1940 1941 if args.auto_script_command == 'inputs': 1942 print ','.join(inputs) 1943 elif args.auto_script_command == 'outputs': 1944 print ','.join(outputs) 1945 else: 1946 print('Invalid script parameters') 1947 return 1 1948 return 0 1949 1950 # Generate files based on GLSL + ESSL symbols 1951 generate_files(False, args, functions_txt_filename, variables_json_filename, 1952 'ImmutableString_autogen.cpp', test_filename, 1953 'tree_util/BuiltIn_complete_autogen.h', 'SymbolTable_autogen.cpp', 1954 'ParseContext_complete_autogen.h', 'SymbolTable_autogen.h') 1955 1956 # Generate files based on only ESSL symbols 1957 # Symbol table with GLSL + ESSL symbols is too large for Android 1958 generate_files(True, args, functions_txt_filename, variables_json_filename, 1959 'ImmutableString_ESSL_autogen.cpp', essl_test_filename, 1960 'tree_util/BuiltIn_ESSL_autogen.h', 'SymbolTable_ESSL_autogen.cpp', 1961 'ParseContext_ESSL_autogen.h', 'SymbolTable_autogen.h') 1962 1963 return 0 1964 1965 1966if __name__ == '__main__': 1967 sys.exit(main()) 1968