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