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