1#!/usr/bin/env vpython3 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 perfect_hash import generate_hash, Hash2 19import argparse 20import copy 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 2020 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 2020 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 2020 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 2020 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 2020 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_operator_header = """// GENERATED FILE - DO NOT EDIT. 388// Generated by {script_name} using data from {function_data_source_name}. 389// 390// Copyright 2021 The ANGLE Project Authors. All rights reserved. 391// Use of this source code is governed by a BSD-style license that can be 392// found in the LICENSE file. 393// 394// Operator_autogen.h: 395// Operators used by the high-level (parse tree) representation. 396 397#ifndef COMPILER_TRANSLATOR_OPERATOR_AUTOGEN_H_ 398#define COMPILER_TRANSLATOR_OPERATOR_AUTOGEN_H_ 399 400#include <stdint.h> 401 402namespace sh 403{{ 404 405enum TOperator : uint16_t 406{{ 407 EOpNull, // if in a node, should only mean a node is still being built 408 409 // Call a function defined in the AST. This might be a user-defined function or a function 410 // inserted by an AST transformation. 411 EOpCallFunctionInAST, 412 413 // Call an internal helper function with a raw implementation - the implementation can't be 414 // subject to AST transformations. Raw functions have a few constraints to keep them compatible 415 // with AST traversers: 416 // * They should not return arrays. 417 // * They should not have out parameters. 418 // TODO: remove this. http://anglebug.com/6059 419 EOpCallInternalRawFunction, 420 421 // 422 // Branch (TIntermBranch) 423 // 424 425 EOpKill, // Fragment only 426 EOpReturn, 427 EOpBreak, 428 EOpContinue, 429 430 // 431 // Constructor (TIntermAggregate) 432 // 433 434 EOpConstruct, 435 436 // 437 // Unary operators with special GLSL syntax (TIntermUnary). 438 // 439 440 EOpNegative, 441 EOpPositive, 442 EOpLogicalNot, 443 EOpBitwiseNot, 444 445 EOpPostIncrement, 446 EOpPostDecrement, 447 EOpPreIncrement, 448 EOpPreDecrement, 449 450 EOpArrayLength, 451 452 // 453 // Binary operators with special GLSL syntax (TIntermBinary). 454 // 455 456 EOpAdd, 457 EOpSub, 458 EOpMul, 459 EOpDiv, 460 EOpIMod, 461 462 EOpEqual, 463 EOpNotEqual, 464 EOpLessThan, 465 EOpGreaterThan, 466 EOpLessThanEqual, 467 EOpGreaterThanEqual, 468 469 EOpComma, 470 471 EOpVectorTimesScalar, 472 EOpVectorTimesMatrix, 473 EOpMatrixTimesVector, 474 EOpMatrixTimesScalar, 475 EOpMatrixTimesMatrix, 476 477 EOpLogicalOr, 478 EOpLogicalXor, 479 EOpLogicalAnd, 480 481 EOpBitShiftLeft, 482 EOpBitShiftRight, 483 484 EOpBitwiseAnd, 485 EOpBitwiseXor, 486 EOpBitwiseOr, 487 488 EOpIndexDirect, 489 EOpIndexIndirect, 490 EOpIndexDirectStruct, 491 EOpIndexDirectInterfaceBlock, 492 493 // 494 // Moves (TIntermBinary) 495 // 496 497 EOpAssign, 498 EOpInitialize, 499 EOpAddAssign, 500 EOpSubAssign, 501 502 EOpMulAssign, 503 EOpVectorTimesMatrixAssign, 504 EOpVectorTimesScalarAssign, 505 EOpMatrixTimesScalarAssign, 506 EOpMatrixTimesMatrixAssign, 507 508 EOpDivAssign, 509 EOpIModAssign, 510 EOpBitShiftLeftAssign, 511 EOpBitShiftRightAssign, 512 EOpBitwiseAndAssign, 513 EOpBitwiseXorAssign, 514 EOpBitwiseOrAssign, 515 516 // Not an op, but a marker for the start of built-in ops. 517 EOpLastNonBuiltIn = EOpBitwiseOrAssign, 518 519 // 520 // Built-in functions mapped to operators (either unary (TIntermUnary) or with multiple 521 // parameters (TIntermAggregate)) 522 // 523 {operator_enum_declarations} 524}}; 525 526// Returns the string corresponding to the operator in GLSL. For built-in functions use the 527// function name directly. 528const char *GetOperatorString(TOperator op); 529 530// Say whether or not a binary or unary operation changes the value of a variable. 531bool IsAssignment(TOperator op); 532 533namespace BuiltInGroup 534{{ 535static inline bool IsBuiltIn(TOperator op) 536{{ 537 return op > EOpLastNonBuiltIn; 538}} 539{is_in_group_definitions} 540}} // namespace BuiltInGroup 541 542}} // namespace sh 543 544#endif // COMPILER_TRANSLATOR_OPERATOR_AUTOGEN_H_ 545 546""" 547 548template_rule = """Rule::Get<{spec}, {version}, {shaders}, {extension}>({symbol_or_var})""" 549 550basic_types_enumeration = [ 551 'Void', 552 'Float', 553 'Double', 554 'Int', 555 'UInt', 556 'Bool', 557 'AtomicCounter', 558 'YuvCscStandardEXT', 559 'Sampler2D', 560 'Sampler3D', 561 'SamplerCube', 562 'Sampler2DArray', 563 'SamplerExternalOES', 564 'SamplerExternal2DY2YEXT', 565 'Sampler2DRect', 566 'Sampler2DMS', 567 'Sampler2DMSArray', 568 'ISampler2D', 569 'ISampler3D', 570 'ISamplerCube', 571 'ISampler2DArray', 572 'ISampler2DMS', 573 'ISampler2DMSArray', 574 'USampler2D', 575 'USampler3D', 576 'USamplerCube', 577 'USampler2DArray', 578 'USampler2DMS', 579 'USampler2DMSArray', 580 'Sampler2DShadow', 581 'SamplerCubeShadow', 582 'Sampler2DArrayShadow', 583 'Sampler1D', 584 'Sampler1DArray', 585 'Sampler1DArrayShadow', 586 'SamplerBuffer', 587 'SamplerCubeArray', 588 'SamplerCubeArrayShadow', 589 'Sampler1DShadow', 590 'Sampler2DRectShadow', 591 'ISampler1D', 592 'ISampler1DArray', 593 'ISampler2DRect', 594 'ISamplerBuffer', 595 'ISamplerCubeArray', 596 'USampler1D', 597 'USampler1DArray', 598 'USampler2DRect', 599 'USamplerBuffer', 600 'USamplerCubeArray', 601 'SamplerVideoWEBGL', 602 'Image2D', 603 'Image3D', 604 'Image2DArray', 605 'ImageCube', 606 'Image1D', 607 'Image1DArray', 608 'Image2DMS', 609 'Image2DMSArray', 610 'ImageCubeArray', 611 'ImageRect', 612 'ImageBuffer', 613 'IImage2D', 614 'IImage3D', 615 'IImage2DArray', 616 'IImageCube', 617 'IImage1D', 618 'IImage1DArray', 619 'IImage2DMS', 620 'IImage2DMSArray', 621 'IImageCubeArray', 622 'IImageRect', 623 'IImageBuffer', 624 'UImage2D', 625 'UImage3D', 626 'UImage2DArray', 627 'UImageCube', 628 'UImage1D', 629 'UImage1DArray', 630 'UImage2DMS', 631 'UImage2DMSArray', 632 'UImageCubeArray', 633 'UImageRect', 634 'UImageBuffer', 635 'SubpassInput', 636 'ISubpassInput', 637 'USubpassInput', 638 'SubpassInputMS', 639 'ISubpassInputMS', 640 'USubpassInputMS', 641] 642 643id_counter = 0 644 645 646def set_working_dir(): 647 script_dir = os.path.dirname(os.path.abspath(__file__)) 648 os.chdir(script_dir) 649 650 651def get_basic_mangled_name(basic): 652 index = basic_types_enumeration.index(basic) 653 if index < 26: 654 return '0' + chr(ord('A') + index) 655 if index < 52: 656 return '0' + chr(ord('a') + index - 26) 657 if index < 78: 658 return '1' + chr(ord('A') + index - 52) 659 return '1' + chr(ord('a') + index - 78) 660 661 662essl_levels = [ 663 'ESSL3_2_BUILTINS', 'ESSL3_1_BUILTINS', 'ESSL3_BUILTINS', 'ESSL1_BUILTINS', 'COMMON_BUILTINS' 664] 665 666glsl_levels = [ 667 'GLSL4_6_BUILTINS', 'GLSL4_5_BUILTINS', 'GLSL4_4_BUILTINS', 'GLSL4_3_BUILTINS', 668 'GLSL4_2_BUILTINS', 'GLSL4_1_BUILTINS', 'GLSL4_BUILTINS', 'GLSL3_3_BUILTINS', 669 'GLSL1_5_BUILTINS', 'GLSL1_4_BUILTINS', 'GLSL1_3_BUILTINS', 'GLSL1_2_BUILTINS', 670 'COMMON_BUILTINS' 671] 672 673 674def generate_suffix_from_level(level): 675 assert (level[:4] == 'GLSL' or level[:4] == 'ESSL') 676 assert (level[-9:] == '_BUILTINS') 677 678 # Turn XYSLN_M_BUILTINS to XYN_M 679 return level[:2] + level[4:-9] 680 681 682def get_essl_shader_version_for_level(level): 683 if level == None: 684 return '-1' 685 elif level == 'ESSL3_2_BUILTINS': 686 return '320' 687 elif level == 'ESSL3_1_BUILTINS': 688 return '310' 689 elif level == 'ESSL3_BUILTINS': 690 return '300' 691 elif level == 'ESSL1_BUILTINS': 692 return '100' 693 elif level == 'COMMON_BUILTINS': 694 return '0' 695 else: 696 raise Exception('Unsupported symbol table level') 697 698 699def get_glsl_shader_version_for_level(level): 700 if level == None: 701 return '-1' 702 elif level == 'GLSL1_2_BUILTINS': 703 return '120' 704 elif level == 'GLSL1_3_BUILTINS': 705 return '130' 706 elif level == 'GLSL1_4_BUILTINS': 707 return '140' 708 elif level == 'GLSL1_5_BUILTINS': 709 return '150' 710 elif level == 'GLSL3_3_BUILTINS': 711 return '330' 712 elif level == 'GLSL4_BUILTINS': 713 return '400' 714 elif level == 'GLSL4_1_BUILTINS': 715 return '410' 716 elif level == 'GLSL4_2_BUILTINS': 717 return '420' 718 elif level == 'GLSL4_3_BUILTINS': 719 return '430' 720 elif level == 'GLSL4_4_BUILTINS': 721 return '440' 722 elif level == 'GLSL4_5_BUILTINS': 723 return '450' 724 elif level == 'GLSL4_6_BUILTINS': 725 return '460' 726 elif level == 'COMMON_BUILTINS': 727 return '0' 728 else: 729 raise Exception('Unsupported symbol table level') 730 731 732def get_shader_version_for_level(spec, level): 733 if spec == "ESSL": 734 return get_essl_shader_version_for_level(level) 735 else: 736 return get_glsl_shader_version_for_level(level) 737 738 739def get_extension_list(extensions): 740 extension_list = [ext.strip() for ext in extensions.split(',')] 741 extension_string = ', '.join(['TExtension::' + ext for ext in extension_list]) 742 return 'std::array<TExtension, ' + str(len(extension_list)) + 'u>{{' + extension_string + '}}' 743 744 745class GroupedList: 746 """"Class for storing a list of objects grouped by symbol table level and condition.""" 747 748 def __init__(self, hashfn, num_names): 749 self.objs = OrderedDict() 750 self.max_name_length = 0 751 self.hashfn = hashfn 752 self.num_names = num_names 753 self.rule_offset = 0 754 755 def add_entry(self, essl_level, glsl_level, shader_type, name, symbol, essl_extension, 756 glsl_extension, script_generated_hash_tests): 757 if essl_level and essl_level not in essl_levels: 758 raise Exception('Unexpected essl level: ' + str(essl_level)) 759 if glsl_level and glsl_level not in glsl_levels: 760 raise Exception('Unexpected glsl level: ' + str(glsl_level)) 761 if len(name) > self.max_name_length: 762 self.max_name_length = len(name) 763 764 name_hash = mangledNameHash(name, self.hashfn, script_generated_hash_tests, False) 765 if name_hash not in self.objs: 766 self.objs[name_hash] = OrderedDict() 767 768 self.objs[name_hash]['name'] = name 769 770 if essl_extension == 'UNDEFINED' and glsl_extension == 'UNDEFINED': 771 if 'symbol' in self.objs[name_hash] and self.objs[name_hash]['symbol'] != symbol: 772 # Adding a variable that is part of two ESSL extensions that have become core 773 if 'symbol2' not in self.objs[name_hash]: 774 if essl_level: 775 self.objs[name_hash]['essl_level2'] = essl_level 776 if glsl_level: 777 self.objs[name_hash]['glsl_level2'] = glsl_level 778 self.objs[name_hash]['symbol2'] = symbol 779 self.objs[name_hash]['shader_type2'] = shader_type 780 elif 'symbol3' not in self.objs[name_hash]: 781 if essl_level: 782 self.objs[name_hash]['essl_level3'] = essl_level 783 if glsl_level: 784 self.objs[name_hash]['glsl_level3'] = glsl_level 785 self.objs[name_hash]['symbol3'] = symbol 786 self.objs[name_hash]['shader_type3'] = shader_type 787 elif 'symbol4' not in self.objs[name_hash]: 788 if essl_level: 789 self.objs[name_hash]['essl_level4'] = essl_level 790 if glsl_level: 791 self.objs[name_hash]['glsl_level4'] = glsl_level 792 self.objs[name_hash]['symbol4'] = symbol 793 self.objs[name_hash]['shader_type4'] = shader_type 794 else: 795 assert (False) 796 else: 797 if essl_level: 798 self.objs[name_hash]['essl_level'] = essl_level 799 if glsl_level: 800 self.objs[name_hash]['glsl_level'] = glsl_level 801 self.objs[name_hash]['symbol'] = symbol 802 self.objs[name_hash]['shader_type'] = shader_type 803 804 if essl_extension != 'UNDEFINED': 805 if ('essl_ext_symbol' in self.objs[name_hash] and 806 self.objs[name_hash]['essl_ext_symbol'] != symbol): 807 # Adding a variable that is part of two ESSL extensions 808 if 'essl_ext_symbol2' not in self.objs[name_hash]: 809 self.objs[name_hash]['essl_extension2'] = essl_extension 810 self.objs[name_hash]['essl_ext_level2'] = essl_level 811 self.objs[name_hash]['essl_ext_symbol2'] = symbol 812 self.objs[name_hash]['essl_ext_shader_type2'] = shader_type 813 elif 'essl_ext_symbol3' not in self.objs[name_hash]: 814 self.objs[name_hash]['essl_extension3'] = essl_extension 815 self.objs[name_hash]['essl_ext_level3'] = essl_level 816 self.objs[name_hash]['essl_ext_symbol3'] = symbol 817 self.objs[name_hash]['essl_ext_shader_type3'] = shader_type 818 elif 'essl_ext_symbol4' not in self.objs[name_hash]: 819 self.objs[name_hash]['essl_extension4'] = essl_extension 820 self.objs[name_hash]['essl_ext_level4'] = essl_level 821 self.objs[name_hash]['essl_ext_symbol4'] = symbol 822 self.objs[name_hash]['essl_ext_shader_type4'] = shader_type 823 else: 824 assert (False) 825 else: 826 self.objs[name_hash]['essl_extension'] = essl_extension 827 self.objs[name_hash]['essl_ext_level'] = essl_level 828 self.objs[name_hash]['essl_ext_symbol'] = symbol 829 self.objs[name_hash]['essl_ext_shader_type'] = shader_type 830 831 if glsl_extension != 'UNDEFINED': 832 self.objs[name_hash]['glsl_extension'] = glsl_extension 833 self.objs[name_hash]['glsl_ext_level'] = glsl_level 834 self.objs[name_hash]['glsl_ext_symbol'] = symbol 835 self.objs[name_hash]['glsl_ext_shader_type'] = shader_type 836 837 def get_max_name_length(self): 838 return self.max_name_length 839 840 def format_rule(self, rule): 841 return template_rule.format(**rule) 842 843 def format_rules(self, rules): 844 return ", ".join([self.format_rule(rule) for rule in rules]) 845 846 def get_rules(self): 847 return self.rules 848 849 def get_names(self): 850 return self.names 851 852 def get_offsets(self): 853 return self.offsets 854 855 def update_arrays(self): 856 857 def add_rule(rules, spec, level, shaders, extension, symbol): 858 var = ("&TableBase::%s" % symbol) if symbol.startswith("m_gl") else None 859 860 extension_list = [] 861 specField = "Spec::%s" % ("ESSL" if spec == "ESSL" else "GLSL") 862 versionField = get_shader_version_for_level(spec, level) 863 shadersField = "Shader::%s" % ("ALL" if shaders == "NONE" else shaders) 864 symbolOrVarField = symbol.replace("Func::", "") if var is None else var 865 if extension != None: 866 extension_list = [ext.strip() for ext in extension.split(',')] 867 for ext in extension_list: 868 rules.append({ 869 "spec": specField, 870 "version": versionField, 871 "shaders": shadersField, 872 "extension": "0" if ext == None else "EXT_INDEX(%s)" % ext, 873 "symbol_or_var": symbolOrVarField 874 }) 875 else: 876 rules.append({ 877 "spec": specField, 878 "version": versionField, 879 "shaders": shadersField, 880 "extension": "0", 881 "symbol_or_var": symbolOrVarField 882 }) 883 884 self.names = [] 885 self.offsets = [] 886 self.rules = [] 887 for hash_val in range(0, self.num_names): 888 if hash_val in self.objs: 889 data = self.objs[hash_val] 890 891 rules = [] 892 893 if "symbol" in data and "essl_level" in data: 894 add_rule(rules, "ESSL", data['essl_level'], data['shader_type'], None, 895 data["symbol"]) 896 897 if "symbol" in data and "glsl_level" in data: 898 add_rule(rules, "GLSL", data['glsl_level'], data['shader_type'], None, 899 data["symbol"]) 900 901 if "symbol2" in data and "essl_level2" in data: 902 add_rule(rules, "ESSL", data['essl_level2'], data['shader_type2'], None, 903 data["symbol2"]) 904 905 if "symbol2" in data and "glsl_level2" in data: 906 add_rule(rules, "GLSL", data['glsl_level2'], data['shader_type2'], None, 907 data["symbol2"]) 908 909 if "symbol3" in data and "essl_level3" in data: 910 add_rule(rules, "ESSL", data['essl_level3'], data['shader_type3'], None, 911 data["symbol3"]) 912 913 if "symbol3" in data and "glsl_level3" in data: 914 add_rule(rules, "GLSL", data['glsl_level3'], data['shader_type3'], None, 915 data["symbol3"]) 916 917 if "symbol4" in data and "essl_level4" in data: 918 add_rule(rules, "ESSL", data['essl_level4'], data['shader_type4'], None, 919 data["symbol4"]) 920 921 if "symbol4" in data and "glsl_level4" in data: 922 add_rule(rules, "GLSL", data['glsl_level4'], data['shader_type4'], None, 923 data["symbol4"]) 924 925 if "essl_ext_symbol" in data: 926 add_rule(rules, "ESSL", data["essl_ext_level"], data["essl_ext_shader_type"], 927 data["essl_extension"], data["essl_ext_symbol"]) 928 929 if "glsl_ext_symbol" in data: 930 add_rule(rules, "GLSL", data["glsl_ext_level"], data["glsl_ext_shader_type"], 931 data["glsl_extension"], data["glsl_ext_symbol"]) 932 933 if "essl_ext_symbol2" in data: 934 add_rule(rules, "ESSL", data["essl_ext_level2"], data["essl_ext_shader_type2"], 935 data["essl_extension2"], data["essl_ext_symbol2"]) 936 937 if "essl_ext_symbol3" in data: 938 add_rule(rules, "ESSL", data["essl_ext_level3"], data["essl_ext_shader_type3"], 939 data["essl_extension3"], data["essl_ext_symbol3"]) 940 941 if "essl_ext_symbol4" in data: 942 add_rule(rules, "ESSL", data["essl_ext_level4"], data["essl_ext_shader_type4"], 943 data["essl_extension4"], data["essl_ext_symbol4"]) 944 945 name = data['name'] 946 name_underscore = name.replace("(", "_") 947 948 self.names.append('"%s"' % name) 949 self.offsets.append("%d, // %s" % (self.rule_offset, name_underscore)) 950 self.rules.append("%s" % self.format_rules(rules)) 951 952 self.rule_offset += len(rules) 953 954 else: 955 self.names.append('""') 956 self.offsets.append('%d, // Empty' % self.rule_offset) 957 958 959class UnmangledGroupedList: 960 """"Class for storing a list of unmangled objects grouped by symbol table level and condition.""" 961 962 def __init__(self, hashfn, num_names): 963 self.objs = OrderedDict() 964 self.max_name_length = 0 965 self.hashfn = hashfn 966 self.num_names = num_names 967 968 def add_entry(self, essl_level, glsl_level, shader_type, name, essl_ext, glsl_ext, 969 essl_extension, glsl_extension, unmangled_script_generated_hash_tests): 970 if essl_level and essl_level not in essl_levels: 971 raise Exception('Unexpected essl level: ' + str(essl_level)) 972 if glsl_level and glsl_level not in glsl_levels: 973 raise Exception('Unexpected glsl level: ' + str(glsl_level)) 974 if len(name) > self.max_name_length: 975 self.max_name_length = len(name) 976 977 name_hash = mangledNameHash(name, self.hashfn, unmangled_script_generated_hash_tests, True) 978 self.objs[name_hash] = OrderedDict() 979 self.objs[name_hash]['name'] = name 980 self.objs[name_hash]['essl_level'] = essl_level 981 self.objs[name_hash]['glsl_level'] = glsl_level 982 self.objs[name_hash]['shader_type'] = shader_type 983 self.objs[name_hash]['essl_ext'] = essl_ext 984 self.objs[name_hash]['glsl_ext'] = glsl_ext 985 self.objs[name_hash]['essl_extension'] = essl_extension 986 self.objs[name_hash]['glsl_extension'] = glsl_extension 987 988 def has_key(self, essl_level, glsl_level, shader_type, name): 989 name_hash = mangledNameHash(name, self.hashfn, None, True, False) 990 if name_hash not in self.objs: 991 return False 992 entry = self.objs[name_hash] 993 if entry['essl_level'] != essl_level: 994 return False 995 if entry['glsl_level'] != glsl_level: 996 return False 997 if entry['shader_type'] != shader_type: 998 return False 999 return True 1000 1001 def get(self, essl_level, glsl_level, shader_type, name): 1002 if self.has_key(essl_level, glsl_level, shader_type, name): 1003 name_hash = mangledNameHash(name, self.hashfn, None, True, False) 1004 return self.objs[name_hash] 1005 return None 1006 1007 def get_max_name_length(self): 1008 return self.max_name_length 1009 1010 def get_array(self): 1011 code = [] 1012 for hash_val in range(0, self.num_names): 1013 obj = self.objs[hash_val] 1014 essl_level = obj['essl_level'] 1015 glsl_level = obj['glsl_level'] 1016 shader_type = 'Shader::' + obj['shader_type'] if obj[ 1017 'shader_type'] != 'NONE' else 'Shader::ALL' 1018 data = [] 1019 data.append('"{name}"'.format(name=obj['name'])) 1020 essl_extensions = [ext.strip() for ext in obj['essl_extension'].split(',')] 1021 template_extensions = 'std::array<TExtension, {count}>{{{{{extensions}}}}}' 1022 data.append( 1023 template_extensions.format( 1024 count=len(essl_extensions), 1025 extensions=','.join(['Ext::' + ext for ext in essl_extensions]))) 1026 data.append("Ext::" + obj['glsl_extension']) 1027 data.append(get_essl_shader_version_for_level(essl_level)) 1028 data.append(get_glsl_shader_version_for_level(glsl_level)) 1029 data.append(shader_type) 1030 1031 code.append('{%s}' % ', '.join(data)) 1032 return code 1033 1034 1035class TType: 1036 1037 def __init__(self, glsl_header_type): 1038 if isinstance(glsl_header_type, str): 1039 self.data = self.parse_type(glsl_header_type) 1040 else: 1041 self.data = glsl_header_type 1042 self.normalize() 1043 1044 def normalize(self): 1045 # Note that this will set primarySize and secondarySize also on genTypes. In that case they 1046 # are overridden when the specific types are generated. 1047 if 'primarySize' not in self.data: 1048 if ('secondarySize' in self.data): 1049 raise Exception( 1050 'Unexpected secondarySize on type that does not have primarySize set') 1051 self.data['primarySize'] = 1 1052 if 'secondarySize' not in self.data: 1053 self.data['secondarySize'] = 1 1054 if 'precision' not in self.data: 1055 self.data['precision'] = 'Undefined' 1056 if 'qualifier' not in self.data: 1057 self.data['qualifier'] = 'Global' 1058 1059 def has_array_size(self): 1060 return 'arraySize' in self.data 1061 1062 def get_statictype_string(self): 1063 template_type = 'StaticType::Get<Ebt{basic}, Ebp{precision}, Evq{qualifier}, {primarySize}, {secondarySize}>()' 1064 if self.has_array_size(): 1065 template_type = 'StaticType::GetArray<Ebt{basic}, Ebp{precision}, Evq{qualifier}, {primarySize}, {secondarySize}, kArraySize{arraySize}, 1>()' 1066 return template_type.format(**self.data) 1067 1068 def get_dynamic_type_string(self): 1069 template_type = 'new TType(Ebt{basic}, Ebp{precision}, Evq{qualifier}, {primarySize}, {secondarySize}' 1070 if self.has_array_size(): 1071 template_type += ', TVector<unsigned int>{{{arraySize}}}' 1072 template_type += ')' 1073 return template_type.format(**self.data) 1074 1075 def get_mangled_name(self): 1076 mangled_name = '' 1077 1078 size_key = (self.data['secondarySize'] - 1) * 4 + self.data['primarySize'] - 1 1079 if size_key < 10: 1080 mangled_name += chr(ord('0') + size_key) 1081 else: 1082 mangled_name += chr(ord('A') + size_key - 10) 1083 mangled_name += get_basic_mangled_name(self.data['basic']) 1084 if self.has_array_size(): 1085 mangled_name += 'x' + str(self.data['arraySize']) 1086 return mangled_name 1087 1088 def get_human_readable_name(self): 1089 name = self.data['basic'] 1090 if self.has_array_size(): 1091 name = str(self.data['arraySize']) + 'x' + name 1092 name += str(self.data['primarySize']) 1093 if self.data['secondarySize'] > 1: 1094 name += 'x' + str(self.data['secondarySize']) 1095 return name 1096 1097 def is_vector(self): 1098 return self.data['primarySize'] > 1 and self.data['secondarySize'] == 1 1099 1100 def is_matrix(self): 1101 return self.data['secondarySize'] > 1 1102 1103 def get_object_size(self): 1104 return self.data['primarySize'] * self.data['secondarySize'] 1105 1106 def specific_sampler_or_image_or_subpass_type(self, basic_type_prefix): 1107 if 'genType' in self.data and self.data['genType'] == 'sampler_or_image_or_subpass': 1108 type = {} 1109 if 'basic' not in self.data: 1110 type['basic'] = {'': 'Float', 'I': 'Int', 'U': 'UInt'}[basic_type_prefix] 1111 type['primarySize'] = self.data['primarySize'] 1112 else: 1113 type['basic'] = basic_type_prefix + self.data['basic'] 1114 type['primarySize'] = 1 1115 type['precision'] = 'Undefined' 1116 return TType(type) 1117 return self 1118 1119 def specific_type(self, vec_size): 1120 type = {} 1121 if 'genType' in self.data: 1122 type['basic'] = self.data['basic'] 1123 type['precision'] = self.data['precision'] 1124 type['qualifier'] = self.data['qualifier'] 1125 type['primarySize'] = vec_size 1126 type['secondarySize'] = 1 1127 return TType(type) 1128 return self 1129 1130 def parse_type(self, glsl_header_type): 1131 # TODO(http://anglebug.com/3833): handle readonly, writeonly qualifiers 1132 if glsl_header_type.startswith('readonly writeonly '): 1133 type_obj = self.parse_type(glsl_header_type[19:]) 1134 type_obj['qualifier'] = 'Readonly Writeonly' 1135 return type_obj 1136 if glsl_header_type.startswith('readonly '): 1137 type_obj = self.parse_type(glsl_header_type[9:]) 1138 type_obj['qualifier'] = 'Readonly' 1139 return type_obj 1140 if glsl_header_type.startswith('writeonly '): 1141 type_obj = self.parse_type(glsl_header_type[10:]) 1142 type_obj['qualifier'] = 'Writeonly' 1143 return type_obj 1144 if glsl_header_type.startswith('out '): 1145 type_obj = self.parse_type(glsl_header_type[4:]) 1146 type_obj['qualifier'] = 'Out' 1147 return type_obj 1148 if glsl_header_type.startswith('inout '): 1149 type_obj = self.parse_type(glsl_header_type[6:]) 1150 type_obj['qualifier'] = 'InOut' 1151 return type_obj 1152 1153 basic_type_map = { 1154 'float': 'Float', 1155 'int': 'Int', 1156 'uint': 'UInt', 1157 'double': 'Double', 1158 'bool': 'Bool', 1159 'void': 'Void', 1160 'atomic_uint': 'AtomicCounter', 1161 'yuvCscStandardEXT': 'YuvCscStandardEXT' 1162 } 1163 1164 if glsl_header_type in basic_type_map: 1165 return {'basic': basic_type_map[glsl_header_type]} 1166 1167 type_obj = {} 1168 1169 basic_type_prefix_map = { 1170 '': 'Float', 1171 'i': 'Int', 1172 'u': 'UInt', 1173 'd': 'Double', 1174 'b': 'Bool', 1175 'v': 'Void' 1176 } 1177 1178 vec_re = re.compile(r'^([iudb]?)vec([234]?)((\[[234]\])?)$') 1179 vec_match = vec_re.match(glsl_header_type) 1180 if vec_match: 1181 type_obj['basic'] = basic_type_prefix_map[vec_match.group(1)] 1182 if vec_match.group(2) == '': 1183 # Type like "ivec" that represents either ivec2, ivec3 or ivec4 1184 type_obj['genType'] = 'vec' 1185 else: 1186 # vec with specific size 1187 if vec_match.group(3) != '': 1188 # vec array 1189 type_obj['primarySize'] = int(vec_match.group(2)) 1190 type_obj['arraySize'] = int(vec_match.group(3)[1]) 1191 else: 1192 type_obj['primarySize'] = int(vec_match.group(2)) 1193 return type_obj 1194 1195 mat_re = re.compile(r'^mat([234])(x([234]))?$') 1196 mat_match = mat_re.match(glsl_header_type) 1197 if mat_match: 1198 type_obj['basic'] = 'Float' 1199 if len(glsl_header_type) == 4: 1200 mat_size = int(mat_match.group(1)) 1201 type_obj['primarySize'] = mat_size 1202 type_obj['secondarySize'] = mat_size 1203 else: 1204 type_obj['primarySize'] = int(mat_match.group(1)) 1205 type_obj['secondarySize'] = int(mat_match.group(3)) 1206 return type_obj 1207 1208 gen_re = re.compile(r'^gen([IUDB]?)Type$') 1209 gen_match = gen_re.match(glsl_header_type) 1210 if gen_match: 1211 type_obj['basic'] = basic_type_prefix_map[gen_match.group(1).lower()] 1212 type_obj['genType'] = 'yes' 1213 return type_obj 1214 1215 if glsl_header_type.startswith('sampler'): 1216 type_obj['basic'] = glsl_header_type[0].upper() + glsl_header_type[1:] 1217 return type_obj 1218 1219 if glsl_header_type.startswith('gsampler') or glsl_header_type.startswith( 1220 'gimage') or glsl_header_type.startswith('gsubpassInput'): 1221 type_obj['basic'] = glsl_header_type[1].upper() + glsl_header_type[2:] 1222 type_obj['genType'] = 'sampler_or_image_or_subpass' 1223 return type_obj 1224 1225 if glsl_header_type == 'gvec4': 1226 return {'primarySize': 4, 'genType': 'sampler_or_image_or_subpass'} 1227 if glsl_header_type == 'gvec3': 1228 return {'primarySize': 3, 'genType': 'sampler_or_image_or_subpass'} 1229 1230 if glsl_header_type == 'IMAGE_PARAMS': 1231 return {'genType': 'image_params'} 1232 1233 raise Exception('Unrecognized type: ' + str(glsl_header_type)) 1234 1235 1236class SymbolsData: 1237 1238 def __init__(self): 1239 1240 # Declarations of symbol unique ids 1241 self.builtin_id_declarations = [] 1242 1243 # Definitions of symbol unique ids needed for those ids used outside of constexpr expressions. 1244 self.builtin_id_definitions = [] 1245 1246 # Declarations of name string variables 1247 self.name_declarations = set() 1248 1249 # Code for testing that script-generated hashes match with runtime computed hashes. 1250 self.script_generated_hash_tests = OrderedDict() 1251 self.unmangled_script_generated_hash_tests = OrderedDict() 1252 1253 1254class VariablesData: 1255 1256 def __init__(self): 1257 1258 # Code for defining TVariables stored as members of TSymbolTable. 1259 self.declare_member_variables = [] 1260 self.init_member_variables = [] 1261 1262 # Declarations of static array sizes if any builtin TVariable is array. 1263 self.type_array_sizes_declarations = set() 1264 1265 # Declarations of builtin TVariables 1266 self.variable_declarations = [] 1267 1268 # Functions for querying the pointer to a specific TVariable. 1269 self.get_variable_declarations = [] 1270 self.get_variable_definitions = [] 1271 1272 1273class FunctionsData: 1274 1275 def __init__(self): 1276 1277 # Declarations of builtin TFunctions 1278 self.function_declarations = [] 1279 1280 # TOperator enum values (and grouping comments) for built-in functions. 1281 self.operator_list = dict() 1282 self.operator_enum_declarations = [] 1283 1284 # Functions for testing whether a builtin belongs in group. 1285 self.is_in_group_definitions = [] 1286 1287 # Declarations of parameter arrays for builtin TFunctions. Map from C++ variable name to the 1288 # full declaration. 1289 self.parameter_declarations = {} 1290 1291 self.defined_function_variants = set() 1292 self.defined_parameter_names = set() 1293 1294 def find_op(self, search_index, direction, limit_for_assertion): 1295 1296 while True: 1297 # Make sure the group is not empty. An "opSuffix" must be used to distinguish between 1298 # built-ins with the same name, but in different groups. 1299 assert (search_index != limit_for_assertion) 1300 1301 line = self.operator_enum_declarations[search_index].lstrip() 1302 if line.startswith('EOp'): 1303 return line[:line.index(',')] 1304 search_index += direction 1305 1306 1307class HashFunction: 1308 1309 def __init__(self, f1, f2, G): 1310 self.f1 = f1 1311 self.f2 = f2 1312 self.G = G 1313 1314 def hash(self, key): 1315 return (self.G[self.f1(key)] + self.G[self.f2(key)]) % len(self.G) 1316 1317 1318def get_parsed_functions(functions_txt_filename, essl_only): 1319 1320 def parse_function_parameters(parameters): 1321 if parameters == '': 1322 return [] 1323 parametersOut = [] 1324 parameters = parameters.split(', ') 1325 for parameter in parameters: 1326 parametersOut.append(TType(parameter.strip())) 1327 return parametersOut 1328 1329 lines = [] 1330 with open(functions_txt_filename) as f: 1331 lines = f.readlines() 1332 lines = [ 1333 line.strip() for line in lines if line.strip() != '' and not line.strip().startswith('//') 1334 ] 1335 1336 fun_re = re.compile(r'^(\w+) (\w+)\((.*)\);$') 1337 1338 parsed_functions = OrderedDict() 1339 group_stack = [] 1340 default_metadata = {} 1341 1342 for line in lines: 1343 if line.startswith('GROUP BEGIN '): 1344 group_rest = line[12:].strip() 1345 group_parts = group_rest.split(' ', 1) 1346 current_group = {'functions': [], 'name': group_parts[0], 'subgroups': {}} 1347 if len(group_parts) > 1: 1348 group_metadata = json.loads(group_parts[1]) 1349 current_group.update(group_metadata) 1350 group_stack.append(current_group) 1351 elif line.startswith('GROUP END '): 1352 group_end_name = line[10:].strip() 1353 current_group = group_stack[-1] 1354 if current_group['name'] != group_end_name: 1355 raise Exception('GROUP END: Unexpected function group name "' + group_end_name + 1356 '" was expecting "' + current_group['name'] + '"') 1357 group_stack.pop() 1358 is_top_level_group = (len(group_stack) == 0) 1359 if is_top_level_group: 1360 if current_group['name'] in parsed_functions: 1361 raise Exception('GROUP END: Duplicate group name "%s"' % current_group['name']) 1362 parsed_functions[current_group['name']] = current_group 1363 default_metadata = {} 1364 else: 1365 super_group = group_stack[-1] 1366 super_group['subgroups'][current_group['name']] = current_group 1367 elif line.startswith('DEFAULT METADATA'): 1368 line_rest = line[16:].strip() 1369 default_metadata = json.loads(line_rest) 1370 else: 1371 fun_match = fun_re.match(line) 1372 if fun_match: 1373 return_type = fun_match.group(1) 1374 name = fun_match.group(2) 1375 parameters = fun_match.group(3) 1376 function_props = { 1377 'name': name, 1378 'returnType': TType(return_type), 1379 'parameters': parse_function_parameters(parameters) 1380 } 1381 function_props.update(default_metadata) 1382 if essl_only: 1383 # Skip GLSL-only functions 1384 if 'essl_level' in function_props: 1385 group_stack[-1]['functions'].append(function_props) 1386 else: 1387 group_stack[-1]['functions'].append(function_props) 1388 else: 1389 raise Exception('Unexpected function input line: ' + line) 1390 1391 return parsed_functions 1392 1393 1394def mangledNameHash(str, hashfn, script_generated_hash_tests, unmangled, save_test=True): 1395 hash = hashfn.hash(str) 1396 if save_test: 1397 confidence_check = '' 1398 if unmangled: 1399 confidence_check = ' ASSERT_EQ(0x{hash}u, ImmutableString("{str}").unmangledNameHash());'.format( 1400 hash=('%08x' % hash), str=str) 1401 else: 1402 confidence_check = ' ASSERT_EQ(0x{hash}u, ImmutableString("{str}").mangledNameHash());'.format( 1403 hash=('%08x' % hash), str=str) 1404 script_generated_hash_tests.update({confidence_check: None}) 1405 return hash 1406 1407 1408def get_function_names(group, mangled_names, unmangled_names): 1409 if 'functions' in group: 1410 for function_props in group['functions']: 1411 function_name = function_props['name'] 1412 unmangled_names.append(function_name) 1413 function_variants = gen_function_variants(function_props) 1414 for function_props in function_variants: 1415 parameters = get_parameters(function_props) 1416 mangled_names.append(get_function_mangled_name(function_name, parameters)) 1417 if 'subgroups' in group: 1418 for subgroup_name, subgroup in group['subgroups'].items(): 1419 get_function_names(subgroup, mangled_names, unmangled_names) 1420 1421 1422def get_variable_names(group, mangled_names): 1423 if 'variables' in group: 1424 for variable_name, props in group['variables'].items(): 1425 mangled_names.append(variable_name) 1426 if 'subgroups' in group: 1427 for subgroup_name, subgroup in group['subgroups'].items(): 1428 get_variable_names(subgroup, mangled_names) 1429 1430 1431def get_suffix(props): 1432 if 'suffix' in props: 1433 return props['suffix'] 1434 return '' 1435 1436 1437def get_essl_extension(props): 1438 if 'essl_extension' in props: 1439 return props['essl_extension'] 1440 return 'UNDEFINED' 1441 1442 1443def get_glsl_extension(props): 1444 if 'glsl_extension' in props: 1445 return props['glsl_extension'] 1446 return 'UNDEFINED' 1447 1448 1449def get_op(name, function_props, group_op_suffix): 1450 return 'EOp' + name[0].upper() + name[1:] + group_op_suffix + function_props.get( 1451 'opSuffix', '') 1452 1453 1454def get_known_to_not_have_side_effects(function_props): 1455 if 'hasSideEffects' in function_props: 1456 return 'false' 1457 else: 1458 for param in get_parameters(function_props): 1459 if 'qualifier' in param.data and (param.data['qualifier'] == 'Out' or 1460 param.data['qualifier'] == 'InOut'): 1461 return 'false' 1462 return 'true' 1463 1464 1465def get_parameters(function_props): 1466 if 'parameters' in function_props: 1467 return function_props['parameters'] 1468 return [] 1469 1470 1471def get_function_mangled_name(function_name, parameters): 1472 mangled_name = function_name + '(' 1473 for param in parameters: 1474 mangled_name += param.get_mangled_name() 1475 return mangled_name 1476 1477 1478def get_function_human_readable_name(function_name, parameters): 1479 name = function_name 1480 for param in parameters: 1481 name += '_' + param.get_human_readable_name() 1482 return name 1483 1484 1485def get_unique_identifier_name(function_name, parameters): 1486 unique_name = function_name + '_' 1487 for param in parameters: 1488 unique_name += param.get_mangled_name() 1489 return unique_name 1490 1491 1492def get_variable_name_to_store_parameter(param): 1493 unique_name = 'pt' 1494 if 'qualifier' in param.data: 1495 if param.data['qualifier'] == 'Out': 1496 unique_name += '_o_' 1497 if param.data['qualifier'] == 'InOut': 1498 unique_name += '_io_' 1499 unique_name += param.get_mangled_name() 1500 return unique_name 1501 1502 1503def get_variable_name_to_store_parameters(parameters): 1504 if len(parameters) == 0: 1505 return 'empty' 1506 unique_name = 'p' 1507 for param in parameters: 1508 if 'qualifier' in param.data: 1509 if param.data['qualifier'] == 'Out': 1510 unique_name += '_o_' 1511 if param.data['qualifier'] == 'InOut': 1512 unique_name += '_io_' 1513 unique_name += param.get_mangled_name() 1514 return unique_name 1515 1516 1517def define_constexpr_type_array_sizes(template_args, type_array_sizes_declarations): 1518 template_array_sizes_declaration = 'constexpr const unsigned int kArraySize{arraySize}[1] = {{{arraySize}}};' 1519 type_array_sizes_declarations.add(template_array_sizes_declaration.format(**template_args)) 1520 1521 1522def define_constexpr_variable(template_args, variable_declarations): 1523 template_args['extension'] = get_extension_list(template_args['extension']) 1524 template_variable_declaration = 'constexpr const TVariable k{name_with_suffix}(BuiltInId::{name_with_suffix}, BuiltInName::{name}, SymbolType::BuiltIn, {extension}, {type});' 1525 1526 variable_declarations.append(template_variable_declaration.format(**template_args)) 1527 1528 1529def gen_function_variants(function_props): 1530 function_variants = [] 1531 parameters = get_parameters(function_props) 1532 function_is_gen_type = False 1533 gen_type = set() 1534 image_params_index = 0 1535 for param in parameters + [function_props['returnType']]: 1536 if 'genType' in param.data: 1537 if param.data['genType'] not in [ 1538 'sampler_or_image_or_subpass', 'vec', 'yes', 'image_params' 1539 ]: 1540 raise Exception( 1541 'Unexpected value of genType "' + str(param.data['genType']) + 1542 '" should be "sampler_or_image_or_subpass", "vec", "yes", or "image_params"') 1543 gen_type.add(param.data['genType']) 1544 if param.data['genType'] == 'image_params': 1545 image_params_index = parameters.index(param) 1546 1547 if len(gen_type) == 0: 1548 function_variants.append(function_props) 1549 return function_variants 1550 1551 # If we have image_params then we're generating variants for 33 separate functions, 1552 # each for a different type of image variable 1553 if 'image_params' in gen_type: 1554 variants = [['gimage2D', 'ivec2'], ['gimage3D', 'ivec3'], ['gimageCube', 'ivec3'], 1555 ['gimageBuffer', 'int'], ['gimage2DArray', 'ivec3'], 1556 ['gimageCubeArray', 'ivec3'], ['gimage1D', 'int'], ['gimage1DArray', 'ivec2'], 1557 ['gimageRect', 'ivec2'], ['gimage2DMS', 'ivec2', 'int'], 1558 ['gimage2DMSArray', 'ivec3', 'int']] 1559 for variant in variants: 1560 image_variant_parameters = [] 1561 for param in parameters: 1562 if parameters.index(param) == image_params_index: 1563 for variant_param in variant: 1564 image_variant_parameters.append(TType(variant_param)) 1565 else: 1566 image_variant_parameters.append(param) 1567 types = ['', 'I', 'U'] 1568 for type in types: 1569 variant_props = function_props.copy() 1570 variant_parameters = [] 1571 for param in image_variant_parameters: 1572 variant_parameters.append( 1573 param.specific_sampler_or_image_or_subpass_type(type)) 1574 variant_props['parameters'] = variant_parameters 1575 variant_props['returnType'] = function_props[ 1576 'returnType'].specific_sampler_or_image_or_subpass_type(type) 1577 function_variants.append(variant_props) 1578 return function_variants 1579 1580 # If we have a gsampler_or_image_or_subpass then we're generating variants for float, int and uint 1581 # samplers. 1582 if 'sampler_or_image_or_subpass' in gen_type: 1583 types = ['', 'I', 'U'] 1584 for type in types: 1585 variant_props = function_props.copy() 1586 variant_parameters = [] 1587 for param in parameters: 1588 variant_parameters.append(param.specific_sampler_or_image_or_subpass_type(type)) 1589 variant_props['parameters'] = variant_parameters 1590 variant_props['returnType'] = function_props[ 1591 'returnType'].specific_sampler_or_image_or_subpass_type(type) 1592 function_variants.append(variant_props) 1593 return function_variants 1594 1595 # If we have a normal gentype then we're generating variants for different sizes of vectors. 1596 sizes = range(1, 5) 1597 if 'vec' in gen_type: 1598 sizes = range(2, 5) 1599 for size in sizes: 1600 variant_props = function_props.copy() 1601 variant_parameters = [] 1602 for param in parameters: 1603 variant_parameters.append(param.specific_type(size)) 1604 variant_props['parameters'] = variant_parameters 1605 variant_props['returnType'] = function_props['returnType'].specific_type(size) 1606 function_variants.append(variant_props) 1607 return function_variants 1608 1609 1610def process_single_function(shader_type, group_name, function_props, symbols, variables, functions, 1611 group_op_suffix, unmangled_function_if_statements, mangled_builtins): 1612 global id_counter 1613 1614 function_name = function_props['name'] 1615 essl_level = function_props['essl_level'] if 'essl_level' in function_props else None 1616 glsl_level = function_props['glsl_level'] if 'glsl_level' in function_props else None 1617 essl_extension = get_essl_extension(function_props) 1618 glsl_extension = get_glsl_extension(function_props) 1619 extension = essl_extension if essl_extension != 'UNDEFINED' else glsl_extension 1620 op = get_op(function_name, function_props, group_op_suffix) 1621 template_args = { 1622 'name': function_name, 1623 'name_with_suffix': function_name + get_suffix(function_props), 1624 'essl_level': essl_level, 1625 'glsl_level': glsl_level, 1626 'essl_extension': essl_extension, 1627 'glsl_extension': glsl_extension, 1628 # This assumes that functions cannot be part of an ESSL and GLSL extension 1629 # Will need to update after adding GLSL extension functions if this is not the case 1630 'extension': essl_extension if essl_extension != 'UNDEFINED' else glsl_extension, 1631 'op': op, 1632 'known_to_not_have_side_effects': get_known_to_not_have_side_effects(function_props) 1633 } 1634 1635 function_variants = gen_function_variants(function_props) 1636 1637 template_name_declaration = 'constexpr const ImmutableString {name_with_suffix}("{name}");' 1638 name_declaration = template_name_declaration.format(**template_args) 1639 if not name_declaration in symbols.name_declarations: 1640 symbols.name_declarations.add(name_declaration) 1641 1642 essl_ext = '{essl_extension}'.format(**template_args) 1643 glsl_ext = '{glsl_extension}'.format(**template_args) 1644 unmangled_builtin_no_shader_type = unmangled_function_if_statements.get( 1645 essl_level, glsl_level, 'NONE', function_name) 1646 if unmangled_builtin_no_shader_type != None and unmangled_builtin_no_shader_type[ 1647 'essl_extension'] == 'UNDEFINED' and unmangled_builtin_no_shader_type[ 1648 'glsl_extension'] == 'UNDEFINED': 1649 # We already have this unmangled name without a shader type nor extension on the same level. 1650 # No need to add a duplicate with a type. 1651 pass 1652 elif (not unmangled_function_if_statements.has_key( 1653 essl_level, glsl_level, shader_type, function_name)) or ( 1654 unmangled_builtin_no_shader_type and 1655 ((essl_extension == 'UNDEFINED' and 1656 unmangled_builtin_no_shader_type['essl_extension'] != 'UNDEFINED') or 1657 (glsl_extension == 'UNDEFINED' and 1658 unmangled_builtin_no_shader_type['glsl_extension'] != 'UNDEFINED'))): 1659 unmangled_function_if_statements.add_entry(essl_level, glsl_level, shader_type, 1660 function_name, essl_ext, glsl_ext, 1661 essl_extension, glsl_extension, 1662 symbols.unmangled_script_generated_hash_tests) 1663 1664 extension_string = get_extension_list(template_args['extension']) 1665 1666 if op not in functions.operator_list: 1667 functions.operator_list[op] = group_name 1668 is_unary = group_name.startswith('Math') and len(get_parameters(function_variants[0])) == 1 1669 assert (not is_unary or 1670 all([len(get_parameters(props)) == 1 for props in function_variants])) 1671 1672 template_operator_enum = ' {op},{is_unary_comment}' 1673 template_args['is_unary_comment'] = ' // Unary' if is_unary else '' 1674 1675 functions.operator_enum_declarations.append(template_operator_enum.format(**template_args)) 1676 else: 1677 # Ensure that built-ins in different groups don't generate the same op. The Is<Group> query 1678 # functions rely on this. 1679 previous_group_name = functions.operator_list[op] 1680 if group_name != previous_group_name: 1681 print('Op ' + op + ' found in group ' + group_name + ' but was previously in group ' + 1682 previous_group_name) 1683 assert (group_name == previous_group_name) 1684 1685 for function_props in function_variants: 1686 template_args['id'] = id_counter 1687 1688 parameters = get_parameters(function_props) 1689 1690 template_args['unique_name'] = get_unique_identifier_name( 1691 template_args['name_with_suffix'], parameters) 1692 template_args['param_count'] = len(parameters) 1693 template_args['return_type'] = function_props['returnType'].get_statictype_string() 1694 template_args['mangled_name'] = get_function_mangled_name(function_name, parameters) 1695 template_args['human_readable_name'] = get_function_human_readable_name( 1696 template_args['name_with_suffix'], parameters) 1697 template_args['mangled_name_length'] = len(template_args['mangled_name']) 1698 1699 symbol = '&Func::{unique_name}'.format(**template_args) 1700 mangled_builtins.add_entry(essl_level, glsl_level, shader_type, 1701 template_args['mangled_name'], symbol, 1702 template_args['essl_extension'], 1703 template_args['glsl_extension'], 1704 symbols.script_generated_hash_tests) 1705 1706 if template_args['unique_name'] in functions.defined_function_variants: 1707 continue 1708 functions.defined_function_variants.add(template_args['unique_name']) 1709 1710 template_builtin_id_declaration = ' static constexpr const TSymbolUniqueId {human_readable_name} = TSymbolUniqueId({id});' 1711 symbols.builtin_id_declarations.append( 1712 template_builtin_id_declaration.format(**template_args)) 1713 template_builtin_id_definition = 'constexpr const TSymbolUniqueId BuiltInId::{human_readable_name};' 1714 symbols.builtin_id_definitions.append( 1715 template_builtin_id_definition.format(**template_args)) 1716 1717 parameters_list = [] 1718 for param in parameters: 1719 unique_param_name = get_variable_name_to_store_parameter(param) 1720 param_template_args = { 1721 'name': '_empty', 1722 'name_with_suffix': unique_param_name, 1723 'type': param.get_statictype_string(), 1724 'extension': 'UNDEFINED' 1725 } 1726 if unique_param_name not in functions.defined_parameter_names: 1727 id_counter += 1 1728 param_template_args['id'] = id_counter 1729 template_builtin_id_declaration = ' static constexpr const TSymbolUniqueId {name_with_suffix} = TSymbolUniqueId({id});' 1730 symbols.builtin_id_declarations.append( 1731 template_builtin_id_declaration.format(**param_template_args)) 1732 define_constexpr_variable(param_template_args, variables.variable_declarations) 1733 functions.defined_parameter_names.add(unique_param_name) 1734 if param.has_array_size(): 1735 array_size_template_args = {'arraySize': param.data['arraySize']} 1736 define_constexpr_type_array_sizes(array_size_template_args, 1737 variables.type_array_sizes_declarations) 1738 parameters_list.append( 1739 '&BuiltInVariable::k{name_with_suffix}'.format(**param_template_args)) 1740 1741 template_args['parameters_var_name'] = get_variable_name_to_store_parameters(parameters) 1742 if len(parameters) > 0: 1743 template_args['parameters_list'] = ', '.join(parameters_list) 1744 template_parameter_list_declaration = 'constexpr const TVariable *{parameters_var_name}[{param_count}] = {{ {parameters_list} }};' 1745 functions.parameter_declarations[ 1746 template_args['parameters_var_name']] = template_parameter_list_declaration.format( 1747 **template_args) 1748 else: 1749 template_parameter_list_declaration = 'constexpr const TVariable **{parameters_var_name} = nullptr;' 1750 functions.parameter_declarations[ 1751 template_args['parameters_var_name']] = template_parameter_list_declaration.format( 1752 **template_args) 1753 1754 template_args['extension'] = extension_string 1755 template_function_declaration = 'constexpr const TFunction {unique_name}(BuiltInId::{human_readable_name}, BuiltInName::{name_with_suffix}, {extension}, BuiltInParameters::{parameters_var_name}, {param_count}, {return_type}, {op}, {known_to_not_have_side_effects});' 1756 functions.function_declarations.append( 1757 template_function_declaration.format(**template_args)) 1758 1759 id_counter += 1 1760 1761 1762def process_single_function_group(shader_type, group_name, group, symbols, variables, functions, 1763 group_op_suffix, unmangled_function_if_statements, 1764 mangled_builtins): 1765 1766 if 'functions' not in group: 1767 return 1768 1769 for function_props in group['functions']: 1770 process_single_function(shader_type, group_name, function_props, symbols, variables, 1771 functions, group_op_suffix, unmangled_function_if_statements, 1772 mangled_builtins) 1773 1774 if 'essl_extension_becomes_core_in' in function_props: 1775 assert ('essl_extension' in function_props) 1776 1777 core_props = copy.deepcopy(function_props) 1778 1779 # Adjust the props by updating the level, removing extension and adding suffix 1780 core_level = function_props['essl_extension_becomes_core_in'] 1781 core_props['essl_level'] = core_level 1782 del core_props['essl_extension'] 1783 suffix = core_props['suffix'] if 'suffix' in core_props else '' 1784 suffix += generate_suffix_from_level(core_level) 1785 core_props['suffix'] = suffix 1786 1787 process_single_function(shader_type, group_name, core_props, symbols, variables, 1788 functions, group_op_suffix, unmangled_function_if_statements, 1789 mangled_builtins) 1790 1791 1792def process_function_group(group_name, group, symbols, variables, functions, 1793 parent_group_op_suffix, unmangled_function_if_statements, 1794 mangled_builtins): 1795 1796 functions.operator_enum_declarations.append('') 1797 functions.operator_enum_declarations.append(' // Group ' + group_name) 1798 first_op_index = len(functions.operator_enum_declarations) 1799 1800 shader_type = 'NONE' 1801 if 'shader_type' in group: 1802 shader_type = group['shader_type'] 1803 1804 group_op_suffix = parent_group_op_suffix + group.get('opSuffix', '') 1805 process_single_function_group(shader_type, group_name, group, symbols, variables, functions, 1806 group_op_suffix, unmangled_function_if_statements, 1807 mangled_builtins) 1808 1809 if 'subgroups' in group: 1810 for subgroup_name, subgroup in group['subgroups'].items(): 1811 process_function_group(group_name + subgroup_name, subgroup, symbols, variables, 1812 functions, group_op_suffix, unmangled_function_if_statements, 1813 mangled_builtins) 1814 1815 if 'queryFunction' in group: 1816 last_op_index = len(functions.operator_enum_declarations) - 1 1817 1818 first_op = functions.find_op(first_op_index, +1, last_op_index + 1) 1819 last_op = functions.find_op(last_op_index, -1, first_op_index - 1) 1820 1821 template_args = {'first_op': first_op, 'last_op': last_op, 'group_name': group_name} 1822 template_is_in_group_definition = """static inline bool Is{group_name}(TOperator op) 1823{{ 1824 return op >= {first_op} && op <= {last_op}; 1825}}""" 1826 functions.is_in_group_definitions.append( 1827 template_is_in_group_definition.format(**template_args)) 1828 1829 1830def prune_parameters_arrays(parameter_declarations, function_declarations): 1831 # We can share parameters arrays between functions in case one array is a subarray of another. 1832 parameter_variable_name_replacements = {} 1833 used_param_variable_names = set() 1834 for param_variable_name, param_declaration in sorted( 1835 parameter_declarations.items(), key=lambda item: -len(item[0])): 1836 replaced = False 1837 for used in used_param_variable_names: 1838 if used.startswith(param_variable_name): 1839 parameter_variable_name_replacements[param_variable_name] = used 1840 replaced = True 1841 break 1842 if not replaced: 1843 used_param_variable_names.add(param_variable_name) 1844 1845 for i in range(len(function_declarations)): 1846 for replaced, replacement in parameter_variable_name_replacements.items(): 1847 function_declarations[i] = function_declarations[i].replace( 1848 'BuiltInParameters::' + replaced + ',', 'BuiltInParameters::' + replacement + ',') 1849 1850 return [ 1851 value for key, value in parameter_declarations.items() if key in used_param_variable_names 1852 ] 1853 1854 1855def process_single_variable(shader_type, variable_name, props, symbols, variables, 1856 mangled_builtins): 1857 global id_counter 1858 1859 essl_level = props['essl_level'] if 'essl_level' in props else None 1860 glsl_level = props['glsl_level'] if 'glsl_level' in props else None 1861 template_args = { 1862 'id': 1863 id_counter, 1864 'name': 1865 variable_name, 1866 'name_with_suffix': 1867 variable_name + get_suffix(props), 1868 'essl_level': 1869 essl_level, 1870 'glsl_level': 1871 glsl_level, 1872 'essl_extension': 1873 get_essl_extension(props), 1874 'glsl_extension': 1875 get_glsl_extension(props), 1876 # This assumes that variables cannot be part of an ESSL and GLSL extension 1877 # Will need to update after adding GLSL extension variables if this is not the case 1878 'extension': 1879 get_essl_extension(props) 1880 if get_essl_extension(props) != 'UNDEFINED' else get_glsl_extension(props), 1881 'class': 1882 'TVariable' 1883 } 1884 1885 template_builtin_id_declaration = ' static constexpr const TSymbolUniqueId {name_with_suffix} = TSymbolUniqueId({id});' 1886 symbols.builtin_id_declarations.append(template_builtin_id_declaration.format(**template_args)) 1887 template_builtin_id_definition = 'constexpr const TSymbolUniqueId BuiltInId::{name_with_suffix};' 1888 symbols.builtin_id_definitions.append(template_builtin_id_definition.format(**template_args)) 1889 1890 template_name_declaration = 'constexpr const ImmutableString {name}("{name}");' 1891 symbols.name_declarations.add(template_name_declaration.format(**template_args)) 1892 1893 is_member = True 1894 template_init_variable = '' 1895 1896 extension_string = get_extension_list(template_args['extension']) 1897 1898 if 'type' in props: 1899 if props['type']['basic'] != 'Bool' and 'precision' not in props['type']: 1900 raise Exception('Missing precision for variable ' + variable_name) 1901 template_args['type'] = TType(props['type']).get_statictype_string() 1902 1903 if 'fields' in props: 1904 # Handle struct and interface block definitions. 1905 template_args['class'] = props['class'] 1906 template_args['fields'] = 'fields_{name_with_suffix}'.format(**template_args) 1907 variables.init_member_variables.append( 1908 ' TFieldList *{fields} = new TFieldList();'.format(**template_args)) 1909 for field_name, field_type in props['fields'].items(): 1910 template_args['field_name'] = field_name 1911 template_args['field_type'] = TType(field_type).get_dynamic_type_string() 1912 template_name_declaration = 'constexpr const ImmutableString {field_name}("{field_name}");' 1913 symbols.name_declarations.add(template_name_declaration.format(**template_args)) 1914 template_add_field = ' {fields}->push_back(new TField({field_type}, BuiltInName::{field_name}, zeroSourceLoc, SymbolType::BuiltIn));' 1915 variables.init_member_variables.append(template_add_field.format(**template_args)) 1916 template_args['extension'] = extension_string 1917 template_init_temp_variable = ' {class} *{name_with_suffix} = new {class}(BuiltInId::{name_with_suffix}, BuiltInName::{name}, {extension}, {fields});' 1918 variables.init_member_variables.append(template_init_temp_variable.format(**template_args)) 1919 if 'private' in props and props['private']: 1920 is_member = False 1921 else: 1922 template_init_variable = ' m_{name_with_suffix} = {name_with_suffix};' 1923 1924 elif 'initDynamicType' in props: 1925 # Handle variables whose type can't be expressed as TStaticType 1926 # (type is a struct or has variable array size for example). 1927 template_args['type_name'] = 'type_{name_with_suffix}'.format(**template_args) 1928 template_args['type'] = template_args['type_name'] 1929 template_args['ext_or_core_suffix'] = '' 1930 if 'essl_extension_becomes_core_in' in props and 'essl_extension' not in props: 1931 template_args['ext_or_core_suffix'] = generate_suffix_from_level(props['essl_level']) 1932 template_args['initDynamicType'] = props['initDynamicType'].format(**template_args) 1933 template_args['extension'] = extension_string 1934 template_init_variable = """ {initDynamicType} 1935{type_name}->realize(); 1936m_{name_with_suffix} = new TVariable(BuiltInId::{name_with_suffix}, BuiltInName::{name}, SymbolType::BuiltIn, {extension}, {type});""" 1937 1938 elif 'value' in props: 1939 # Handle variables with constant value, such as gl_MaxDrawBuffers. 1940 if props['value'] != 'resources': 1941 raise Exception('Unrecognized value source in variable properties: ' + 1942 str(props['value'])) 1943 resources_key = variable_name[3:] 1944 if 'valueKey' in props: 1945 resources_key = props['valueKey'] 1946 template_args['value'] = 'resources.' + resources_key 1947 template_args['object_size'] = TType(props['type']).get_object_size() 1948 template_args['extension'] = extension_string 1949 template_init_variable = """ m_{name_with_suffix} = new TVariable(BuiltInId::{name_with_suffix}, BuiltInName::{name}, SymbolType::BuiltIn, {extension}, {type}); 1950{{ 1951 TConstantUnion *unionArray = new TConstantUnion[{object_size}]; 1952 unionArray[0].setIConst({value}); 1953 static_cast<TVariable *>(m_{name_with_suffix})->shareConstPointer(unionArray); 1954}}""" 1955 if template_args['object_size'] > 1: 1956 template_init_variable = """ m_{name_with_suffix} = new TVariable(BuiltInId::{name_with_suffix}, BuiltInName::{name}, SymbolType::BuiltIn, {extension}, {type}); 1957{{ 1958 TConstantUnion *unionArray = new TConstantUnion[{object_size}]; 1959 for (size_t index = 0u; index < {object_size}; ++index) 1960 {{ 1961 unionArray[index].setIConst({value}[index]); 1962 }} 1963 static_cast<TVariable *>(m_{name_with_suffix})->shareConstPointer(unionArray); 1964}}""" 1965 1966 else: 1967 # Handle variables that can be stored as constexpr TVariable like 1968 # gl_Position, gl_FragColor etc. 1969 define_constexpr_variable(template_args, variables.variable_declarations) 1970 is_member = False 1971 1972 template_get_variable_declaration = 'const TVariable *{name_with_suffix}();' 1973 variables.get_variable_declarations.append( 1974 template_get_variable_declaration.format(**template_args)) 1975 1976 template_get_variable_definition = """const TVariable *{name_with_suffix}() 1977{{ 1978return &k{name_with_suffix}; 1979}} 1980""" 1981 variables.get_variable_definitions.append( 1982 template_get_variable_definition.format(**template_args)) 1983 1984 if essl_level != 'GLSL_BUILTINS': 1985 obj = '&BuiltInVariable::k{name_with_suffix}'.format(**template_args) 1986 # TODO(http://anglebug.com/3835): Add GLSL level once GLSL built-in vars are added 1987 mangled_builtins.add_entry(essl_level, 'COMMON_BUILTINS', shader_type, 1988 template_args['name'], obj, template_args['essl_extension'], 1989 template_args['glsl_extension'], 1990 symbols.script_generated_hash_tests) 1991 1992 if is_member: 1993 variables.init_member_variables.append(template_init_variable.format(**template_args)) 1994 1995 template_declare_member_variable = 'TSymbol *m_{name_with_suffix} = nullptr;' 1996 variables.declare_member_variables.append( 1997 template_declare_member_variable.format(**template_args)) 1998 1999 obj = 'm_{name_with_suffix}'.format(**template_args) 2000 2001 # TODO(http://anglebug.com/3835): Add GLSL level once GLSL built-in vars are added 2002 mangled_builtins.add_entry(essl_level, 'COMMON_BUILTINS', shader_type, 2003 template_args['name'], obj, template_args['essl_extension'], 2004 template_args['glsl_extension'], 2005 symbols.script_generated_hash_tests) 2006 2007 id_counter += 1 2008 2009 2010def process_single_variable_group(shader_type, group, symbols, variables, mangled_builtins): 2011 global id_counter 2012 if 'variables' not in group: 2013 return 2014 for variable_name, props in group['variables'].items(): 2015 process_single_variable(shader_type, variable_name, props, symbols, variables, 2016 mangled_builtins) 2017 2018 if 'essl_extension_becomes_core_in' in props: 2019 assert ('essl_extension' in props) 2020 2021 core_props = copy.deepcopy(props) 2022 2023 # Adjust the props by updating the level, removing extension and adding suffix 2024 core_level = props['essl_extension_becomes_core_in'] 2025 core_props['essl_level'] = core_level 2026 del core_props['essl_extension'] 2027 suffix = core_props['suffix'] if 'suffix' in core_props else '' 2028 suffix += generate_suffix_from_level(core_level) 2029 core_props['suffix'] = suffix 2030 process_single_variable(shader_type, variable_name, core_props, symbols, variables, 2031 mangled_builtins) 2032 2033 2034def process_variable_group(shader_type, group_name, group, symbols, variables, mangled_builtins): 2035 global id_counter 2036 2037 if 'shader_type' in group: 2038 shader_type = group['shader_type'] 2039 2040 process_single_variable_group(shader_type, group, symbols, variables, mangled_builtins) 2041 2042 if 'subgroups' in group: 2043 for subgroup_name, subgroup in group['subgroups'].items(): 2044 process_variable_group(shader_type, subgroup_name, subgroup, symbols, variables, 2045 mangled_builtins) 2046 2047 2048def generate_files(essl_only, args, functions_txt_filename, variables_json_filename, 2049 immutablestring_cpp_filename, immutablestringtest_cpp_filename, 2050 builtin_header_filename, symboltable_cpp_filename, operator_header_filename, 2051 symboltable_header_filename): 2052 2053 symbols = SymbolsData() 2054 variables = VariablesData() 2055 functions = FunctionsData() 2056 2057 parsed_functions = get_parsed_functions(functions_txt_filename, essl_only) 2058 2059 if args.dump_intermediate_json: 2060 with open('builtin_functions_ESSL.json' if essl_only else 'builtin_functions.json', 2061 'w') as outfile: 2062 2063 def serialize_obj(obj): 2064 if isinstance(obj, TType): 2065 return obj.data 2066 else: 2067 raise "Cannot serialize to JSON: " + str(obj) 2068 2069 json.dump( 2070 parsed_functions, outfile, indent=4, separators=(',', ': '), default=serialize_obj) 2071 2072 parsed_variables = None 2073 with open(variables_json_filename) as f: 2074 # TODO(http://anglebug.com/3835): skip loading GLSL-only vars when they are added if essl_only 2075 parsed_variables = json.load(f, object_pairs_hook=OrderedDict) 2076 2077 # This script uses a perfect hash function to avoid dealing with collisions 2078 mangled_names = [] 2079 unmangled_names = [] 2080 for group_name, group in parsed_functions.items(): 2081 get_function_names(group, mangled_names, unmangled_names) 2082 for group_name, group in parsed_variables.items(): 2083 get_variable_names(group, mangled_names) 2084 2085 # Hashing mangled names 2086 mangled_names = list(dict.fromkeys(mangled_names)) 2087 num_mangled_names = len(mangled_names) 2088 mangled_names_dict = dict(zip(mangled_names, range(0, len(mangled_names)))) 2089 # Generate the perfect hash function 2090 f1, f2, mangled_G = generate_hash(mangled_names_dict, Hash2) 2091 mangled_hashfn = HashFunction(f1, f2, mangled_G) 2092 mangled_S1 = f1.salt 2093 mangled_S2 = f2.salt 2094 # Array for querying mangled builtins 2095 mangled_builtins = GroupedList(mangled_hashfn, num_mangled_names) 2096 2097 # Hashing unmangled names 2098 unmangled_names = list(dict.fromkeys(unmangled_names)) 2099 num_unmangled_names = len(unmangled_names) 2100 unmangled_names_dict = dict(zip(unmangled_names, range(0, len(unmangled_names)))) 2101 # Generate the perfect hash function 2102 f1, f2, unmangled_G = generate_hash(unmangled_names_dict, Hash2) 2103 unmangled_hashfn = HashFunction(f1, f2, unmangled_G) 2104 unmangled_S1 = f1.salt 2105 unmangled_S2 = f2.salt 2106 # Array for querying unmangled builtins 2107 unmangled_function_if_statements = UnmangledGroupedList(unmangled_hashfn, num_unmangled_names) 2108 2109 for group_name, group in parsed_functions.items(): 2110 process_function_group(group_name, group, symbols, variables, functions, '', 2111 unmangled_function_if_statements, mangled_builtins) 2112 2113 functions.parameter_declarations = prune_parameters_arrays(functions.parameter_declarations, 2114 functions.function_declarations) 2115 2116 for group_name, group in parsed_variables.items(): 2117 process_variable_group('NONE', group_name, group, symbols, variables, mangled_builtins) 2118 2119 mangled_builtins.update_arrays() 2120 2121 output_strings = { 2122 'script_name': 2123 os.path.basename(__file__), 2124 'builtin_id_declarations': 2125 '\n'.join(symbols.builtin_id_declarations), 2126 'builtin_id_definitions': 2127 '\n'.join(symbols.builtin_id_definitions), 2128 'last_builtin_id': 2129 id_counter - 1, 2130 'name_declarations': 2131 '\n'.join(sorted(list(symbols.name_declarations))), 2132 'function_data_source_name': 2133 functions_txt_filename, 2134 'function_declarations': 2135 '\n'.join(functions.function_declarations), 2136 'parameter_declarations': 2137 '\n'.join(sorted(functions.parameter_declarations)), 2138 'operator_enum_declarations': 2139 '\n'.join(functions.operator_enum_declarations), 2140 'is_in_group_definitions': 2141 '\n'.join(functions.is_in_group_definitions), 2142 'variable_data_source_name': 2143 variables_json_filename, 2144 'type_array_sizes_declarations': 2145 '\n'.join(sorted(variables.type_array_sizes_declarations)), 2146 'variable_declarations': 2147 '\n'.join(sorted(variables.variable_declarations)), 2148 'get_variable_declarations': 2149 '\n'.join(sorted(variables.get_variable_declarations)), 2150 'get_variable_definitions': 2151 '\n'.join(sorted(variables.get_variable_definitions)), 2152 'declare_member_variables': 2153 '\n'.join(variables.declare_member_variables), 2154 'init_member_variables': 2155 '\n'.join(variables.init_member_variables), 2156 'mangled_names_array': 2157 ',\n'.join(mangled_builtins.get_names()), 2158 'mangled_offsets_array': 2159 '\n'.join(mangled_builtins.get_offsets()), 2160 'mangled_rules': 2161 ',\n'.join(mangled_builtins.get_rules()), 2162 'unmangled_array': 2163 ', '.join(unmangled_function_if_statements.get_array()), 2164 'max_unmangled_name_length': 2165 unmangled_function_if_statements.get_max_name_length(), 2166 'max_mangled_name_length': 2167 mangled_builtins.get_max_name_length(), 2168 'num_unmangled_names': 2169 num_unmangled_names, 2170 'num_mangled_names': 2171 num_mangled_names, 2172 'script_generated_hash_tests': 2173 '\n'.join(symbols.script_generated_hash_tests.keys()), 2174 'unmangled_script_generated_hash_tests': 2175 '\n'.join(symbols.unmangled_script_generated_hash_tests.keys()), 2176 'mangled_S1': 2177 str(mangled_S1).replace('[', ' ').replace(']', ' '), 2178 'mangled_S2': 2179 str(mangled_S2).replace('[', ' ').replace(']', ' '), 2180 'mangled_G': 2181 str(mangled_G).replace('[', ' ').replace(']', ' '), 2182 'mangled_NG': 2183 len(mangled_G), 2184 'mangled_NS': 2185 len(mangled_S1), 2186 'unmangled_S1': 2187 str(unmangled_S1).replace('[', ' ').replace(']', ' '), 2188 'unmangled_S2': 2189 str(unmangled_S2).replace('[', ' ').replace(']', ' '), 2190 'unmangled_G': 2191 str(unmangled_G).replace('[', ' ').replace(']', ' '), 2192 'unmangled_NG': 2193 len(unmangled_G), 2194 'unmangled_NS': 2195 len(unmangled_S1), 2196 'header_label': 2197 'ESSL_' if essl_only else 'complete_', 2198 'source_label': 2199 'ESSL_' if essl_only else '' 2200 } 2201 2202 with open(immutablestring_cpp_filename, 'wt') as outfile_cpp: 2203 output_cpp = template_immutablestring_cpp.format(**output_strings) 2204 outfile_cpp.write(output_cpp) 2205 2206 with open(immutablestringtest_cpp_filename, 'wt') as outfile_cpp: 2207 output_cpp = template_immutablestringtest_cpp.format(**output_strings) 2208 outfile_cpp.write(output_cpp) 2209 2210 with open(builtin_header_filename, 'wt') as outfile_header: 2211 output_header = template_builtin_header.format(**output_strings) 2212 outfile_header.write(output_header) 2213 2214 with open(symboltable_cpp_filename, 'wt') as outfile_cpp: 2215 output_cpp = template_symboltable_cpp.format(**output_strings) 2216 outfile_cpp.write(output_cpp) 2217 2218 if not essl_only: 2219 with open(operator_header_filename, 'wt') as outfile_header: 2220 output_header = template_operator_header.format(**output_strings) 2221 outfile_header.write(output_header) 2222 2223 with open(symboltable_header_filename, 'wt') as outfile_h: 2224 output_h = template_symboltable_header.format(**output_strings) 2225 outfile_h.write(output_h) 2226 2227 2228def main(): 2229 random.seed(0) 2230 set_working_dir() 2231 2232 parser = argparse.ArgumentParser() 2233 parser.add_argument( 2234 '--dump-intermediate-json', 2235 help='Dump parsed function data as a JSON file builtin_functions.json', 2236 action="store_true") 2237 parser.add_argument('auto_script_command', nargs='?', default='') 2238 args = parser.parse_args() 2239 2240 test_filename = '../../tests/compiler_tests/ImmutableString_test_autogen.cpp' 2241 essl_test_filename = '../../tests/compiler_tests/ImmutableString_test_ESSL_autogen.cpp' 2242 variables_json_filename = 'builtin_variables.json' 2243 functions_txt_filename = 'builtin_function_declarations.txt' 2244 2245 # auto_script parameters. 2246 if args.auto_script_command != '': 2247 inputs = [ 2248 functions_txt_filename, 2249 variables_json_filename, 2250 ] 2251 outputs = [ 2252 'ImmutableString_autogen.cpp', 2253 'Operator_autogen.h', 2254 'SymbolTable_autogen.cpp', 2255 'SymbolTable_autogen.h', 2256 'tree_util/BuiltIn_complete_autogen.h', 2257 test_filename, 2258 'ImmutableString_ESSL_autogen.cpp', 2259 'SymbolTable_ESSL_autogen.cpp', 2260 'tree_util/BuiltIn_ESSL_autogen.h', 2261 essl_test_filename, 2262 ] 2263 2264 if args.auto_script_command == 'inputs': 2265 print(','.join(inputs)) 2266 elif args.auto_script_command == 'outputs': 2267 print(','.join(outputs)) 2268 else: 2269 print('Invalid script parameters') 2270 return 1 2271 return 0 2272 2273 # Generate files based on GLSL + ESSL symbols 2274 generate_files(False, args, functions_txt_filename, variables_json_filename, 2275 'ImmutableString_autogen.cpp', test_filename, 2276 'tree_util/BuiltIn_complete_autogen.h', 'SymbolTable_autogen.cpp', 2277 'Operator_autogen.h', 'SymbolTable_autogen.h') 2278 2279 # Generate files based on only ESSL symbols 2280 # Symbol table with GLSL + ESSL symbols is too large for Android 2281 generate_files(True, args, functions_txt_filename, variables_json_filename, 2282 'ImmutableString_ESSL_autogen.cpp', essl_test_filename, 2283 'tree_util/BuiltIn_ESSL_autogen.h', 'SymbolTable_ESSL_autogen.cpp', 2284 'Operator_autogen.h', 'SymbolTable_autogen.h') 2285 2286 return 0 2287 2288 2289if __name__ == '__main__': 2290 sys.exit(main()) 2291